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

Cover more test/widgets tests with leak tracking #3 (#134576)

parent ba233b8a
......@@ -6,9 +6,10 @@ import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
void main() {
testWidgets('onSaved callback is called', (WidgetTester tester) async {
testWidgetsWithLeakTracking('onSaved callback is called', (WidgetTester tester) async {
final GlobalKey<FormState> formKey = GlobalKey<FormState>();
String? fieldValue;
......@@ -48,7 +49,7 @@ void main() {
await checkText('');
});
testWidgets('onChanged callback is called', (WidgetTester tester) async {
testWidgetsWithLeakTracking('onChanged callback is called', (WidgetTester tester) async {
String? fieldValue;
Widget builder() {
......@@ -85,7 +86,7 @@ void main() {
await checkText('');
});
testWidgets('Validator sets the error text only when validate is called', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Validator sets the error text only when validate is called', (WidgetTester tester) async {
final GlobalKey<FormState> formKey = GlobalKey<FormState>();
String? errorText(String? value) => '${value ?? ''}/error';
......@@ -139,7 +140,7 @@ void main() {
await checkErrorText('');
});
testWidgets('Should announce error text when validate returns error', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Should announce error text when validate returns error', (WidgetTester tester) async {
final GlobalKey<FormState> formKey = GlobalKey<FormState>();
await tester.pumpWidget(
MaterialApp(
......@@ -178,7 +179,7 @@ void main() {
});
testWidgets('isValid returns true when a field is valid', (WidgetTester tester) async {
testWidgetsWithLeakTracking('isValid returns true when a field is valid', (WidgetTester tester) async {
final GlobalKey<FormFieldState<String>> fieldKey1 = GlobalKey<FormFieldState<String>>();
final GlobalKey<FormFieldState<String>> fieldKey2 = GlobalKey<FormFieldState<String>>();
const String validString = 'Valid string';
......@@ -223,7 +224,7 @@ void main() {
expect(fieldKey2.currentState!.isValid, isTrue);
});
testWidgets(
testWidgetsWithLeakTracking(
'isValid returns false when the field is invalid and does not change error display',
(WidgetTester tester) async {
final GlobalKey<FormFieldState<String>> fieldKey1 = GlobalKey<FormFieldState<String>>();
......@@ -272,7 +273,7 @@ void main() {
},
);
testWidgets('Multiple TextFormFields communicate', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Multiple TextFormFields communicate', (WidgetTester tester) async {
final GlobalKey<FormState> formKey = GlobalKey<FormState>();
final GlobalKey<FormFieldState<String>> fieldKey = GlobalKey<FormFieldState<String>>();
// Input 2's validator depends on a input 1's value.
......@@ -322,7 +323,7 @@ void main() {
await checkErrorText('');
});
testWidgets('Provide initial value to input when no controller is specified', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Provide initial value to input when no controller is specified', (WidgetTester tester) async {
const String initialValue = 'hello';
final GlobalKey<FormFieldState<String>> inputKey = GlobalKey<FormFieldState<String>>();
......@@ -366,8 +367,9 @@ void main() {
expect(editableText.widget.controller.text, equals('world'));
});
testWidgets('Controller defines initial value', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Controller defines initial value', (WidgetTester tester) async {
final TextEditingController controller = TextEditingController(text: 'hello');
addTearDown(controller.dispose);
const String initialValue = 'hello';
final GlobalKey<FormFieldState<String>> inputKey = GlobalKey<FormFieldState<String>>();
......@@ -413,10 +415,11 @@ void main() {
expect(controller.text, equals('world'));
});
testWidgets('TextFormField resets to its initial value', (WidgetTester tester) async {
testWidgetsWithLeakTracking('TextFormField resets to its initial value', (WidgetTester tester) async {
final GlobalKey<FormState> formKey = GlobalKey<FormState>();
final GlobalKey<FormFieldState<String>> inputKey = GlobalKey<FormFieldState<String>>();
final TextEditingController controller = TextEditingController(text: 'Plover');
addTearDown(controller.dispose);
Widget builder() {
return MaterialApp(
......@@ -459,9 +462,11 @@ void main() {
expect(controller.text, equals('Plover'));
});
testWidgets('TextEditingController updates to/from form field value', (WidgetTester tester) async {
testWidgetsWithLeakTracking('TextEditingController updates to/from form field value', (WidgetTester tester) async {
final TextEditingController controller1 = TextEditingController(text: 'Foo');
addTearDown(controller1.dispose);
final TextEditingController controller2 = TextEditingController(text: 'Bar');
addTearDown(controller2.dispose);
final GlobalKey<FormFieldState<String>> inputKey = GlobalKey<FormFieldState<String>>();
TextEditingController? currentController;
......@@ -566,7 +571,7 @@ void main() {
expect(controller2.text, equals('Xyzzy'));
});
testWidgets('No crash when a TextFormField is removed from the tree', (WidgetTester tester) async {
testWidgetsWithLeakTracking('No crash when a TextFormField is removed from the tree', (WidgetTester tester) async {
final GlobalKey<FormState> formKey = GlobalKey<FormState>();
String? fieldValue;
......@@ -620,7 +625,7 @@ void main() {
expect(formKey.currentState!.validate(), isTrue);
});
testWidgets('Does not auto-validate before value changes when autovalidateMode is set to onUserInteraction', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Does not auto-validate before value changes when autovalidateMode is set to onUserInteraction', (WidgetTester tester) async {
late FormFieldState<String> formFieldState;
String? errorText(String? value) => '$value/error';
......@@ -656,7 +661,7 @@ void main() {
expect(find.text(errorText('foo')!), findsNothing);
});
testWidgets('auto-validate before value changes if autovalidateMode was set to always', (WidgetTester tester) async {
testWidgetsWithLeakTracking('auto-validate before value changes if autovalidateMode was set to always', (WidgetTester tester) async {
late FormFieldState<String> formFieldState;
String? errorText(String? value) => '$value/error';
......@@ -689,7 +694,7 @@ void main() {
expect(formFieldState.hasError, isTrue);
});
testWidgets('Form auto-validates form fields only after one of them changes if autovalidateMode is onUserInteraction', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Form auto-validates form fields only after one of them changes if autovalidateMode is onUserInteraction', (WidgetTester tester) async {
const String initialValue = 'foo';
String? errorText(String? value) => 'error/$value';
......@@ -743,7 +748,7 @@ void main() {
expect(find.text(errorText(initialValue)!), findsNWidgets(2));
});
testWidgets('Form auto-validates form fields even before any have changed if autovalidateMode is set to always', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Form auto-validates form fields even before any have changed if autovalidateMode is set to always', (WidgetTester tester) async {
String? errorText(String? value) => 'error/$value';
Widget builder() {
......@@ -773,7 +778,7 @@ void main() {
expect(find.text(errorText('')!), findsOneWidget);
});
testWidgets('Form.reset() resets form fields, and auto validation will only happen on the next user interaction if autovalidateMode is onUserInteraction', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Form.reset() resets form fields, and auto validation will only happen on the next user interaction if autovalidateMode is onUserInteraction', (WidgetTester tester) async {
final GlobalKey<FormState> formState = GlobalKey<FormState>();
String? errorText(String? value) => '$value/error';
......@@ -818,7 +823,7 @@ void main() {
});
// Regression test for https://github.com/flutter/flutter/issues/63753.
testWidgets('Validate form should return correct validation if the value is composing', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Validate form should return correct validation if the value is composing', (WidgetTester tester) async {
final GlobalKey<FormState> formKey = GlobalKey<FormState>();
String? fieldValue;
......@@ -855,7 +860,7 @@ void main() {
expect(formKey.currentState!.validate(), isFalse);
});
testWidgets('hasInteractedByUser returns false when the input has not changed', (WidgetTester tester) async {
testWidgetsWithLeakTracking('hasInteractedByUser returns false when the input has not changed', (WidgetTester tester) async {
final GlobalKey<FormFieldState<String>> fieldKey = GlobalKey<FormFieldState<String>>();
final Widget widget = MaterialApp(
......@@ -879,7 +884,7 @@ void main() {
expect(fieldKey.currentState!.hasInteractedByUser, isFalse);
});
testWidgets('hasInteractedByUser returns true after the input has changed', (WidgetTester tester) async {
testWidgetsWithLeakTracking('hasInteractedByUser returns true after the input has changed', (WidgetTester tester) async {
final GlobalKey<FormFieldState<String>> fieldKey = GlobalKey<FormFieldState<String>>();
final Widget widget = MaterialApp(
......@@ -908,7 +913,7 @@ void main() {
expect(fieldKey.currentState!.hasInteractedByUser, isTrue);
});
testWidgets('hasInteractedByUser returns false after the field is reset', (WidgetTester tester) async {
testWidgetsWithLeakTracking('hasInteractedByUser returns false after the field is reset', (WidgetTester tester) async {
final GlobalKey<FormFieldState<String>> fieldKey = GlobalKey<FormFieldState<String>>();
final Widget widget = MaterialApp(
......
......@@ -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('FractionallySizedBox', (WidgetTester tester) async {
testWidgetsWithLeakTracking('FractionallySizedBox', (WidgetTester tester) async {
final GlobalKey inner = GlobalKey();
await tester.pumpWidget(OverflowBox(
minWidth: 0.0,
......@@ -29,7 +30,7 @@ void main() {
expect(box.localToGlobal(Offset.zero), equals(const Offset(25.0, 37.5)));
});
testWidgets('FractionallySizedBox alignment', (WidgetTester tester) async {
testWidgetsWithLeakTracking('FractionallySizedBox alignment', (WidgetTester tester) async {
final GlobalKey inner = GlobalKey();
await tester.pumpWidget(Directionality(
textDirection: TextDirection.rtl,
......@@ -45,7 +46,7 @@ void main() {
expect(box.localToGlobal(box.size.center(Offset.zero)), equals(const Offset(800.0 - 400.0 / 2.0, 0.0 + 300.0 / 2.0)));
});
testWidgets('FractionallySizedBox alignment (direction-sensitive)', (WidgetTester tester) async {
testWidgetsWithLeakTracking('FractionallySizedBox alignment (direction-sensitive)', (WidgetTester tester) async {
final GlobalKey inner = GlobalKey();
await tester.pumpWidget(Directionality(
textDirection: TextDirection.rtl,
......@@ -61,7 +62,7 @@ void main() {
expect(box.localToGlobal(box.size.center(Offset.zero)), equals(const Offset(0.0 + 400.0 / 2.0, 0.0 + 300.0 / 2.0)));
});
testWidgets('OverflowBox alignment with FractionallySizedBox', (WidgetTester tester) async {
testWidgetsWithLeakTracking('OverflowBox alignment with FractionallySizedBox', (WidgetTester tester) async {
final GlobalKey inner = GlobalKey();
await tester.pumpWidget(Directionality(
textDirection: TextDirection.rtl,
......
......@@ -8,6 +8,7 @@ import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
typedef ElementRebuildCallback = void Function(StatefulElement element);
......@@ -22,13 +23,13 @@ class _MyGlobalObjectKey<T extends State<StatefulWidget>> extends GlobalObjectKe
}
void main() {
testWidgets('UniqueKey control test', (WidgetTester tester) async {
testWidgetsWithLeakTracking('UniqueKey control test', (WidgetTester tester) async {
final Key key = UniqueKey();
expect(key, hasOneLineDescription);
expect(key, isNot(equals(UniqueKey())));
});
testWidgets('ObjectKey control test', (WidgetTester tester) async {
testWidgetsWithLeakTracking('ObjectKey control test', (WidgetTester tester) async {
final Object a = Object();
final Object b = Object();
final Key keyA = ObjectKey(a);
......@@ -41,7 +42,7 @@ void main() {
expect(keyA, isNot(equals(keyB)));
});
testWidgets('GlobalObjectKey toString test', (WidgetTester tester) async {
testWidgetsWithLeakTracking('GlobalObjectKey toString test', (WidgetTester tester) async {
const GlobalObjectKey one = GlobalObjectKey(1);
const GlobalObjectKey<TestState> two = GlobalObjectKey<TestState>(2);
const GlobalObjectKey three = _MyGlobalObjectKey(3);
......@@ -53,7 +54,7 @@ void main() {
expect(four.toString(), equals('[_MyGlobalObjectKey<TestState> ${describeIdentity(4)}]'));
});
testWidgets('GlobalObjectKey control test', (WidgetTester tester) async {
testWidgetsWithLeakTracking('GlobalObjectKey control test', (WidgetTester tester) async {
final Object a = Object();
final Object b = Object();
final Key keyA = GlobalObjectKey(a);
......@@ -66,7 +67,7 @@ void main() {
expect(keyA, isNot(equals(keyB)));
});
testWidgets('GlobalKey correct case 1 - can move global key from container widget to layoutbuilder', (WidgetTester tester) async {
testWidgetsWithLeakTracking('GlobalKey correct case 1 - can move global key from container widget to layoutbuilder', (WidgetTester tester) async {
final Key key = GlobalKey(debugLabel: 'correct');
await tester.pumpWidget(Stack(
textDirection: TextDirection.ltr,
......@@ -101,7 +102,7 @@ void main() {
));
});
testWidgets('GlobalKey correct case 2 - can move global key from layoutbuilder to container widget', (WidgetTester tester) async {
testWidgetsWithLeakTracking('GlobalKey correct case 2 - can move global key from layoutbuilder to container widget', (WidgetTester tester) async {
final Key key = GlobalKey(debugLabel: 'correct');
await tester.pumpWidget(Stack(
textDirection: TextDirection.ltr,
......@@ -135,7 +136,7 @@ void main() {
));
});
testWidgets('GlobalKey correct case 3 - can deal with early rebuild in layoutbuilder - move backward', (WidgetTester tester) async {
testWidgetsWithLeakTracking('GlobalKey correct case 3 - can deal with early rebuild in layoutbuilder - move backward', (WidgetTester tester) async {
const Key key1 = GlobalObjectKey('Text1');
const Key key2 = GlobalObjectKey('Text2');
Key? rebuiltKeyOfSecondChildBeforeLayout;
......@@ -224,7 +225,7 @@ void main() {
expect(rebuiltKeyOfSecondChildAfterLayout, key1);
});
testWidgets('GlobalKey correct case 4 - can deal with early rebuild in layoutbuilder - move forward', (WidgetTester tester) async {
testWidgetsWithLeakTracking('GlobalKey correct case 4 - can deal with early rebuild in layoutbuilder - move forward', (WidgetTester tester) async {
const Key key1 = GlobalObjectKey('Text1');
const Key key2 = GlobalObjectKey('Text2');
const Key key3 = GlobalObjectKey('Text3');
......@@ -327,7 +328,7 @@ void main() {
expect(rebuiltKeyOfThirdChildAfterLayout, key2);
});
testWidgets('GlobalKey correct case 5 - can deal with early rebuild in layoutbuilder - only one global key', (WidgetTester tester) async {
testWidgetsWithLeakTracking('GlobalKey correct case 5 - can deal with early rebuild in layoutbuilder - only one global key', (WidgetTester tester) async {
const Key key1 = GlobalObjectKey('Text1');
Key? rebuiltKeyOfSecondChildBeforeLayout;
Key? rebuiltKeyOfThirdChildAfterLayout;
......@@ -418,7 +419,7 @@ void main() {
expect(rebuiltKeyOfThirdChildAfterLayout, key1);
});
testWidgets('GlobalKey duplication 1 - double appearance', (WidgetTester tester) async {
testWidgetsWithLeakTracking('GlobalKey duplication 1 - double appearance', (WidgetTester tester) async {
final Key key = GlobalKey(debugLabel: 'problematic');
await tester.pumpWidget(Stack(
textDirection: TextDirection.ltr,
......@@ -447,7 +448,7 @@ void main() {
);
});
testWidgets('GlobalKey duplication 2 - splitting and changing type', (WidgetTester tester) async {
testWidgetsWithLeakTracking('GlobalKey duplication 2 - splitting and changing type', (WidgetTester tester) async {
final Key key = GlobalKey(debugLabel: 'problematic');
await tester.pumpWidget(Stack(
......@@ -493,7 +494,7 @@ void main() {
);
});
testWidgets('GlobalKey duplication 3 - splitting and changing type', (WidgetTester tester) async {
testWidgetsWithLeakTracking('GlobalKey duplication 3 - splitting and changing type', (WidgetTester tester) async {
final Key key = GlobalKey(debugLabel: 'problematic');
await tester.pumpWidget(Stack(
textDirection: TextDirection.ltr,
......@@ -520,7 +521,7 @@ void main() {
);
});
testWidgets('GlobalKey duplication 4 - splitting and half changing type', (WidgetTester tester) async {
testWidgetsWithLeakTracking('GlobalKey duplication 4 - splitting and half changing type', (WidgetTester tester) async {
final Key key = GlobalKey(debugLabel: 'problematic');
await tester.pumpWidget(Stack(
textDirection: TextDirection.ltr,
......@@ -547,7 +548,7 @@ void main() {
);
});
testWidgets('GlobalKey duplication 5 - splitting and half changing type', (WidgetTester tester) async {
testWidgetsWithLeakTracking('GlobalKey duplication 5 - splitting and half changing type', (WidgetTester tester) async {
final Key key = GlobalKey(debugLabel: 'problematic');
await tester.pumpWidget(Stack(
textDirection: TextDirection.ltr,
......@@ -565,7 +566,7 @@ void main() {
expect(tester.takeException(), isFlutterError);
});
testWidgets('GlobalKey duplication 6 - splitting and not changing type', (WidgetTester tester) async {
testWidgetsWithLeakTracking('GlobalKey duplication 6 - splitting and not changing type', (WidgetTester tester) async {
final Key key = GlobalKey(debugLabel: 'problematic');
await tester.pumpWidget(Stack(
textDirection: TextDirection.ltr,
......@@ -583,7 +584,7 @@ void main() {
expect(tester.takeException(), isFlutterError);
});
testWidgets('GlobalKey duplication 7 - appearing later', (WidgetTester tester) async {
testWidgetsWithLeakTracking('GlobalKey duplication 7 - appearing later', (WidgetTester tester) async {
final Key key = GlobalKey(debugLabel: 'problematic');
await tester.pumpWidget(Stack(
textDirection: TextDirection.ltr,
......@@ -602,7 +603,7 @@ void main() {
expect(tester.takeException(), isFlutterError);
});
testWidgets('GlobalKey duplication 8 - appearing earlier', (WidgetTester tester) async {
testWidgetsWithLeakTracking('GlobalKey duplication 8 - appearing earlier', (WidgetTester tester) async {
final Key key = GlobalKey(debugLabel: 'problematic');
await tester.pumpWidget(Stack(
textDirection: TextDirection.ltr,
......@@ -621,7 +622,7 @@ void main() {
expect(tester.takeException(), isFlutterError);
});
testWidgets('GlobalKey duplication 9 - moving and appearing later', (WidgetTester tester) async {
testWidgetsWithLeakTracking('GlobalKey duplication 9 - moving and appearing later', (WidgetTester tester) async {
final Key key = GlobalKey(debugLabel: 'problematic');
await tester.pumpWidget(Stack(
textDirection: TextDirection.ltr,
......@@ -642,7 +643,7 @@ void main() {
expect(tester.takeException(), isFlutterError);
});
testWidgets('GlobalKey duplication 10 - moving and appearing earlier', (WidgetTester tester) async {
testWidgetsWithLeakTracking('GlobalKey duplication 10 - moving and appearing earlier', (WidgetTester tester) async {
final Key key = GlobalKey(debugLabel: 'problematic');
await tester.pumpWidget(Stack(
textDirection: TextDirection.ltr,
......@@ -663,7 +664,7 @@ void main() {
expect(tester.takeException(), isFlutterError);
});
testWidgets('GlobalKey duplication 11 - double sibling appearance', (WidgetTester tester) async {
testWidgetsWithLeakTracking('GlobalKey duplication 11 - double sibling appearance', (WidgetTester tester) async {
final Key key = GlobalKey(debugLabel: 'problematic');
await tester.pumpWidget(Stack(
textDirection: TextDirection.ltr,
......@@ -675,7 +676,7 @@ void main() {
expect(tester.takeException(), isFlutterError);
});
testWidgets('GlobalKey duplication 12 - all kinds of badness at once', (WidgetTester tester) async {
testWidgetsWithLeakTracking('GlobalKey duplication 12 - all kinds of badness at once', (WidgetTester tester) async {
final Key key1 = GlobalKey(debugLabel: 'problematic');
final Key key2 = GlobalKey(debugLabel: 'problematic'); // intentionally the same label
final Key key3 = GlobalKey(debugLabel: 'also problematic');
......@@ -723,7 +724,7 @@ void main() {
);
});
testWidgets('GlobalKey duplication 13 - all kinds of badness at once', (WidgetTester tester) async {
testWidgetsWithLeakTracking('GlobalKey duplication 13 - all kinds of badness at once', (WidgetTester tester) async {
final Key key1 = GlobalKey(debugLabel: 'problematic');
final Key key2 = GlobalKey(debugLabel: 'problematic'); // intentionally the same label
final Key key3 = GlobalKey(debugLabel: 'also problematic');
......@@ -770,7 +771,7 @@ void main() {
expect(tester.takeException(), isFlutterError);
});
testWidgets('GlobalKey duplication 14 - moving during build - before', (WidgetTester tester) async {
testWidgetsWithLeakTracking('GlobalKey duplication 14 - moving during build - before', (WidgetTester tester) async {
final Key key = GlobalKey(debugLabel: 'problematic');
await tester.pumpWidget(Stack(
textDirection: TextDirection.ltr,
......@@ -789,7 +790,7 @@ void main() {
));
});
testWidgets('GlobalKey duplication 15 - duplicating during build - before', (WidgetTester tester) async {
testWidgetsWithLeakTracking('GlobalKey duplication 15 - duplicating during build - before', (WidgetTester tester) async {
final Key key = GlobalKey(debugLabel: 'problematic');
await tester.pumpWidget(Stack(
textDirection: TextDirection.ltr,
......@@ -810,7 +811,7 @@ void main() {
expect(tester.takeException(), isFlutterError);
});
testWidgets('GlobalKey duplication 16 - moving during build - after', (WidgetTester tester) async {
testWidgetsWithLeakTracking('GlobalKey duplication 16 - moving during build - after', (WidgetTester tester) async {
final Key key = GlobalKey(debugLabel: 'problematic');
await tester.pumpWidget(Stack(
textDirection: TextDirection.ltr,
......@@ -829,7 +830,7 @@ void main() {
));
});
testWidgets('GlobalKey duplication 17 - duplicating during build - after', (WidgetTester tester) async {
testWidgetsWithLeakTracking('GlobalKey duplication 17 - duplicating during build - after', (WidgetTester tester) async {
final Key key = GlobalKey(debugLabel: 'problematic');
await tester.pumpWidget(Stack(
textDirection: TextDirection.ltr,
......@@ -857,7 +858,7 @@ void main() {
expect(count, 1);
});
testWidgets('GlobalKey duplication 18 - subtree build duplicate key with same type', (WidgetTester tester) async {
testWidgetsWithLeakTracking('GlobalKey duplication 18 - subtree build duplicate key with same type', (WidgetTester tester) async {
final Key key = GlobalKey(debugLabel: 'problematic');
final Stack stack = Stack(
textDirection: TextDirection.ltr,
......@@ -894,7 +895,7 @@ void main() {
);
});
testWidgets('GlobalKey duplication 19 - subtree build duplicate key with different types', (WidgetTester tester) async {
testWidgetsWithLeakTracking('GlobalKey duplication 19 - subtree build duplicate key with different types', (WidgetTester tester) async {
final Key key = GlobalKey(debugLabel: 'problematic');
final Stack stack = Stack(
textDirection: TextDirection.ltr,
......@@ -922,7 +923,7 @@ void main() {
);
});
testWidgets('GlobalKey duplication 20 - real duplication with early rebuild in layoutbuilder will throw', (WidgetTester tester) async {
testWidgetsWithLeakTracking('GlobalKey duplication 20 - real duplication with early rebuild in layoutbuilder will throw', (WidgetTester tester) async {
const Key key1 = GlobalObjectKey('Text1');
const Key key2 = GlobalObjectKey('Text2');
Key? rebuiltKeyOfSecondChildBeforeLayout;
......@@ -1023,14 +1024,17 @@ void main() {
);
});
testWidgets('GlobalKey - detach and re-attach child to different parents', (WidgetTester tester) async {
testWidgetsWithLeakTracking('GlobalKey - detach and re-attach child to different parents', (WidgetTester tester) async {
final ScrollController scrollController = ScrollController();
addTearDown(scrollController.dispose);
await tester.pumpWidget(Directionality(
textDirection: TextDirection.ltr,
child: Center(
child: SizedBox(
height: 100,
child: CustomScrollView(
controller: ScrollController(),
controller: scrollController,
slivers: <Widget>[
SliverList(
delegate: SliverChildListDelegate(<Widget>[
......@@ -1058,7 +1062,7 @@ void main() {
element.createChild(0, after: null);
});
testWidgets('GlobalKey - re-attach child to new parents, and the old parent is deactivated(unmounted)', (WidgetTester tester) async {
testWidgetsWithLeakTracking('GlobalKey - re-attach child to new parents, and the old parent is deactivated(unmounted)', (WidgetTester tester) async {
// This is a regression test for https://github.com/flutter/flutter/issues/62055
const Key key1 = GlobalObjectKey('key1');
const Key key2 = GlobalObjectKey('key2');
......@@ -1104,7 +1108,7 @@ void main() {
expect(tabController.index, 0);
});
testWidgets('Defunct setState throws exception', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Defunct setState throws exception', (WidgetTester tester) async {
late StateSetter setState;
await tester.pumpWidget(StatefulBuilder(
......@@ -1122,12 +1126,12 @@ void main() {
expect(() { setState(() { }); }, throwsFlutterError);
});
testWidgets('State toString', (WidgetTester tester) async {
testWidgetsWithLeakTracking('State toString', (WidgetTester tester) async {
final TestState state = TestState();
expect(state.toString(), contains('no widget'));
});
testWidgets('debugPrintGlobalKeyedWidgetLifecycle control test', (WidgetTester tester) async {
testWidgetsWithLeakTracking('debugPrintGlobalKeyedWidgetLifecycle control test', (WidgetTester tester) async {
expect(debugPrintGlobalKeyedWidgetLifecycle, isFalse);
final DebugPrintCallback oldCallback = debugPrint;
......@@ -1150,7 +1154,7 @@ void main() {
expect(log[1], matches('Discarding .+ from inactive elements list.'));
});
testWidgets('MultiChildRenderObjectElement.children', (WidgetTester tester) async {
testWidgetsWithLeakTracking('MultiChildRenderObjectElement.children', (WidgetTester tester) async {
GlobalKey key0, key1, key2;
await tester.pumpWidget(Column(
key: key0 = GlobalKey(),
......@@ -1169,7 +1173,7 @@ void main() {
);
});
testWidgets('Can not attach a non-RenderObjectElement to the MultiChildRenderObjectElement - mount', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Can not attach a non-RenderObjectElement to the MultiChildRenderObjectElement - mount', (WidgetTester tester) async {
await tester.pumpWidget(
Column(
children: <Widget>[
......@@ -1194,7 +1198,7 @@ void main() {
);
});
testWidgets('Can not attach a non-RenderObjectElement to the MultiChildRenderObjectElement - update', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Can not attach a non-RenderObjectElement to the MultiChildRenderObjectElement - update', (WidgetTester tester) async {
await tester.pumpWidget(
Column(
children: <Widget>[
......@@ -1227,7 +1231,7 @@ void main() {
);
});
testWidgets('Element diagnostics', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Element diagnostics', (WidgetTester tester) async {
GlobalKey key0;
await tester.pumpWidget(Column(
key: key0 = GlobalKey(),
......@@ -1319,7 +1323,7 @@ void main() {
}
});
testWidgets('didUpdateDependencies is not called on a State that never rebuilds', (WidgetTester tester) async {
testWidgetsWithLeakTracking('didUpdateDependencies is not called on a State that never rebuilds', (WidgetTester tester) async {
final GlobalKey<DependentState> key = GlobalKey<DependentState>();
/// Initial build - should call didChangeDependencies, not deactivate
......@@ -1348,7 +1352,7 @@ void main() {
expect(state.deactivatedCount, 2);
});
testWidgets('StatefulElement subclass can decorate State.build', (WidgetTester tester) async {
testWidgetsWithLeakTracking('StatefulElement subclass can decorate State.build', (WidgetTester tester) async {
late bool isDidChangeDependenciesDecorated;
late bool isBuildDecorated;
......@@ -1372,7 +1376,7 @@ void main() {
expect(isDidChangeDependenciesDecorated, isFalse);
});
group('BuildContext.debugDoingbuild', () {
testWidgets('StatelessWidget', (WidgetTester tester) async {
testWidgetsWithLeakTracking('StatelessWidget', (WidgetTester tester) async {
late bool debugDoingBuildOnBuild;
await tester.pumpWidget(
StatelessWidgetSpy(
......@@ -1387,7 +1391,7 @@ void main() {
expect(context.debugDoingBuild, isFalse);
expect(debugDoingBuildOnBuild, isTrue);
});
testWidgets('StatefulWidget', (WidgetTester tester) async {
testWidgetsWithLeakTracking('StatefulWidget', (WidgetTester tester) async {
late bool debugDoingBuildOnBuild;
late bool debugDoingBuildOnInitState;
late bool debugDoingBuildOnDidChangeDependencies;
......@@ -1456,11 +1460,12 @@ void main() {
expect(debugDoingBuildOnDispose, isFalse);
expect(debugDoingBuildOnDeactivate, isFalse);
});
testWidgets('RenderObjectWidget', (WidgetTester tester) async {
testWidgetsWithLeakTracking('RenderObjectWidget', (WidgetTester tester) async {
late bool debugDoingBuildOnCreateRenderObject;
bool? debugDoingBuildOnUpdateRenderObject;
bool? debugDoingBuildOnDidUnmountRenderObject;
final ValueNotifier<int> notifier = ValueNotifier<int>(0);
addTearDown(notifier.dispose);
late BuildContext spyContext;
......@@ -1516,7 +1521,7 @@ void main() {
});
});
testWidgets('A widget whose element has an invalid visitChildren implementation triggers a useful error message', (WidgetTester tester) async {
testWidgetsWithLeakTracking('A widget whose element has an invalid visitChildren implementation triggers a useful error message', (WidgetTester tester) async {
final GlobalKey key = GlobalKey();
await tester.pumpWidget(_WidgetWithNoVisitChildren(_StatefulLeaf(key: key)));
(key.currentState! as _StatefulLeafState).markNeedsBuild();
......@@ -1542,11 +1547,13 @@ void main() {
);
});
testWidgets('Can create BuildOwner that does not interfere with pointer router or raw key event handler', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Can create BuildOwner that does not interfere with pointer router or raw key event handler', (WidgetTester tester) async {
final int pointerRouterCount = GestureBinding.instance.pointerRouter.debugGlobalRouteCount;
final RawKeyEventHandler? rawKeyEventHandler = RawKeyboard.instance.keyEventHandler;
expect(rawKeyEventHandler, isNotNull);
BuildOwner(focusManager: FocusManager());
final FocusManager focusManager = FocusManager();
addTearDown(focusManager.dispose);
BuildOwner(focusManager: focusManager);
expect(GestureBinding.instance.pointerRouter.debugGlobalRouteCount, pointerRouterCount);
expect(RawKeyboard.instance.keyEventHandler, same(rawKeyEventHandler));
});
......@@ -1601,7 +1608,7 @@ void main() {
expect(dependenciesProperty.toDescription(), '[ButtonBarTheme, Directionality, FocusTraversalOrder]');
});
testWidgets('BuildOwner.globalKeyCount keeps track of in-use global keys', (WidgetTester tester) async {
testWidgetsWithLeakTracking('BuildOwner.globalKeyCount keeps track of in-use global keys', (WidgetTester tester) async {
final int initialCount = tester.binding.buildOwner!.globalKeyCount;
final GlobalKey key1 = GlobalKey();
final GlobalKey key2 = GlobalKey();
......@@ -1615,7 +1622,7 @@ void main() {
expect(tester.binding.buildOwner!.globalKeyCount, initialCount + 0);
});
testWidgets('Widget and State properties are nulled out when unmounted', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Widget and State properties are nulled out when unmounted', (WidgetTester tester) async {
await tester.pumpWidget(const _StatefulLeaf());
final StatefulElement element = tester.element<StatefulElement>(find.byType(_StatefulLeaf));
expect(element.state, isA<State<_StatefulLeaf>>());
......@@ -1631,7 +1638,7 @@ void main() {
expect(() => element.widget, throwsA(isA<TypeError>()));
});
testWidgets('LayerLink can be swapped between parent and child container layers', (WidgetTester tester) async {
testWidgetsWithLeakTracking('LayerLink can be swapped between parent and child container layers', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/96959.
final LayerLink link = LayerLink();
await tester.pumpWidget(_TestLeaderLayerWidget(
......@@ -1653,7 +1660,7 @@ void main() {
});
testWidgets('Deactivate and activate are called correctly', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Deactivate and activate are called correctly', (WidgetTester tester) async {
final List<String> states = <String>[];
Widget build([Key? key]) {
return StatefulWidgetSpy(
......@@ -1687,7 +1694,7 @@ void main() {
expect(states, <String>['deactivate', 'dispose']);
});
testWidgets('RenderObjectElement.unmount disposes of its renderObject', (WidgetTester tester) async {
testWidgetsWithLeakTracking('RenderObjectElement.unmount disposes of its renderObject', (WidgetTester tester) async {
await tester.pumpWidget(const Placeholder());
final RenderObjectElement element = tester.allElements.whereType<RenderObjectElement>().last;
final RenderObject renderObject = element.renderObject;
......@@ -1699,7 +1706,7 @@ void main() {
expect(renderObject.debugDisposed, true);
});
testWidgets('Getting the render object of an unmounted element throws', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Getting the render object of an unmounted element throws', (WidgetTester tester) async {
await tester.pumpWidget(const _StatefulLeaf());
final StatefulElement element = tester.element<StatefulElement>(find.byType(_StatefulLeaf));
expect(element.state, isA<State<_StatefulLeaf>>());
......@@ -1754,7 +1761,7 @@ The findRenderObject() method was called for the following element:
expect(child.doesDependOnInheritedElement(ancestor), isTrue);
});
testWidgets(
testWidgetsWithLeakTracking(
'MultiChildRenderObjectElement.updateChildren test',
(WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/120762.
......
......@@ -6,11 +6,12 @@ import 'package:flutter/gestures.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
import 'semantics_tester.dart';
void main() {
testWidgets('Vertical gesture detector has up/down actions', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Vertical gesture detector has up/down actions', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester);
int callCount = 0;
......@@ -44,7 +45,7 @@ void main() {
semantics.dispose();
});
testWidgets('Horizontal gesture detector has up/down actions', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Horizontal gesture detector has up/down actions', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester);
int callCount = 0;
......@@ -78,7 +79,7 @@ void main() {
semantics.dispose();
});
testWidgets('All registered handlers for the gesture kind are called', (WidgetTester tester) async {
testWidgetsWithLeakTracking('All registered handlers for the gesture kind are called', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester);
final Set<String> logs = <String>{};
......@@ -102,7 +103,7 @@ void main() {
semantics.dispose();
});
testWidgets('Replacing recognizers should update semantic handlers', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Replacing recognizers should update semantic handlers', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester);
// How the test is set up:
......@@ -173,7 +174,7 @@ void main() {
});
group("RawGestureDetector's custom semantics delegate", () {
testWidgets('should update semantics notations when switching from the default delegate', (WidgetTester tester) async {
testWidgetsWithLeakTracking('should update semantics notations when switching from the default delegate', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester);
final Map<Type, GestureRecognizerFactory> gestures =
_buildGestureMap(() => LongPressGestureRecognizer(), null)
......@@ -208,7 +209,7 @@ void main() {
semantics.dispose();
});
testWidgets('should update semantics notations when switching to the default delegate', (WidgetTester tester) async {
testWidgetsWithLeakTracking('should update semantics notations when switching to the default delegate', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester);
final Map<Type, GestureRecognizerFactory> gestures =
_buildGestureMap(() => LongPressGestureRecognizer(), null)
......@@ -243,7 +244,7 @@ void main() {
semantics.dispose();
});
testWidgets('should update semantics notations when switching from a different custom delegate', (WidgetTester tester) async {
testWidgetsWithLeakTracking('should update semantics notations when switching from a different custom delegate', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester);
final Map<Type, GestureRecognizerFactory> gestures =
_buildGestureMap(() => LongPressGestureRecognizer(), null)
......@@ -279,7 +280,7 @@ void main() {
semantics.dispose();
});
testWidgets('should correctly call callbacks', (WidgetTester tester) async {
testWidgetsWithLeakTracking('should correctly call callbacks', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester);
final List<String> logs = <String>[];
final GlobalKey<RawGestureDetectorState> detectorKey = GlobalKey();
......@@ -321,7 +322,7 @@ void main() {
group("RawGestureDetector's default semantics delegate", () {
group('should map onTap to', () {
testWidgets('null when there is no TapGR', (WidgetTester tester) async {
testWidgetsWithLeakTracking('null when there is no TapGR', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester);
await tester.pumpWidget(
Center(
......@@ -339,7 +340,7 @@ void main() {
semantics.dispose();
});
testWidgets('non-null when there is TapGR with no callbacks', (WidgetTester tester) async {
testWidgetsWithLeakTracking('non-null when there is TapGR with no callbacks', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester);
await tester.pumpWidget(
Center(
......@@ -360,7 +361,7 @@ void main() {
semantics.dispose();
});
testWidgets('a callback that correctly calls callbacks', (WidgetTester tester) async {
testWidgetsWithLeakTracking('a callback that correctly calls callbacks', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester);
final GlobalKey detectorKey = GlobalKey();
final List<String> logs = <String>[];
......@@ -394,7 +395,7 @@ void main() {
});
group('should map onLongPress to', () {
testWidgets('null when there is no LongPressGR ', (WidgetTester tester) async {
testWidgetsWithLeakTracking('null when there is no LongPressGR ', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester);
await tester.pumpWidget(
Center(
......@@ -412,7 +413,7 @@ void main() {
semantics.dispose();
});
testWidgets('non-null when there is LongPressGR with no callbacks', (WidgetTester tester) async {
testWidgetsWithLeakTracking('non-null when there is LongPressGR with no callbacks', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester);
await tester.pumpWidget(
Center(
......@@ -433,7 +434,7 @@ void main() {
semantics.dispose();
});
testWidgets('a callback that correctly calls callbacks', (WidgetTester tester) async {
testWidgetsWithLeakTracking('a callback that correctly calls callbacks', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester);
final GlobalKey detectorKey = GlobalKey();
final List<String> logs = <String>[];
......@@ -466,7 +467,7 @@ void main() {
});
group('should map onHorizontalDragUpdate to', () {
testWidgets('null when there is no matching recognizers ', (WidgetTester tester) async {
testWidgetsWithLeakTracking('null when there is no matching recognizers ', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester);
await tester.pumpWidget(
Center(
......@@ -484,7 +485,7 @@ void main() {
semantics.dispose();
});
testWidgets('non-null when there is either matching recognizer with no callbacks', (WidgetTester tester) async {
testWidgetsWithLeakTracking('non-null when there is either matching recognizer with no callbacks', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester);
await tester.pumpWidget(
Center(
......@@ -526,7 +527,7 @@ void main() {
semantics.dispose();
});
testWidgets('a callback that correctly calls callbacks', (WidgetTester tester) async {
testWidgetsWithLeakTracking('a callback that correctly calls callbacks', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester);
final GlobalKey detectorKey = GlobalKey();
final List<String> logs = <String>[];
......@@ -576,7 +577,7 @@ void main() {
});
group('should map onVerticalDragUpdate to', () {
testWidgets('null when there is no matching recognizers ', (WidgetTester tester) async {
testWidgetsWithLeakTracking('null when there is no matching recognizers ', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester);
await tester.pumpWidget(
Center(
......@@ -594,7 +595,7 @@ void main() {
semantics.dispose();
});
testWidgets('non-null when there is either matching recognizer with no callbacks', (WidgetTester tester) async {
testWidgetsWithLeakTracking('non-null when there is either matching recognizer with no callbacks', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester);
await tester.pumpWidget(
Center(
......@@ -617,7 +618,7 @@ void main() {
semantics.dispose();
});
testWidgets('a callback that correctly calls callbacks', (WidgetTester tester) async {
testWidgetsWithLeakTracking('a callback that correctly calls callbacks', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester);
final GlobalKey detectorKey = GlobalKey();
final List<String> logs = <String>[];
......@@ -666,7 +667,7 @@ void main() {
});
});
testWidgets('should update semantics notations when receiving new gestures', (WidgetTester tester) async {
testWidgetsWithLeakTracking('should update semantics notations when receiving new gestures', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester);
await tester.pumpWidget(
Center(
......
......@@ -6,11 +6,12 @@ import 'package:flutter/gestures.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';
void main() {
const Offset forcePressOffset = Offset(400.0, 50.0);
testWidgets('Uncontested scrolls start immediately', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Uncontested scrolls start immediately', (WidgetTester tester) async {
bool didStartDrag = false;
double? updatedDragDelta;
bool didEndDrag = false;
......@@ -58,7 +59,7 @@ void main() {
await tester.pumpWidget(Container());
});
testWidgets('Match two scroll gestures in succession', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Match two scroll gestures in succession', (WidgetTester tester) async {
int gestureCount = 0;
double dragDistance = 0.0;
......@@ -91,7 +92,7 @@ void main() {
await tester.pumpWidget(Container());
});
testWidgets("Pan doesn't crash", (WidgetTester tester) async {
testWidgetsWithLeakTracking("Pan doesn't crash", (WidgetTester tester) async {
bool didStartPan = false;
Offset? panDelta;
bool didEndPan = false;
......@@ -135,7 +136,7 @@ void main() {
},
);
testWidgets('Translucent', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Translucent', (WidgetTester tester) async {
bool didReceivePointerDown;
bool didTap;
......@@ -206,7 +207,7 @@ void main() {
expect(didTap, isTrue);
}, variant: buttonVariant);
testWidgets('Empty', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Empty', (WidgetTester tester) async {
bool didTap = false;
await tester.pumpWidget(
Center(
......@@ -228,7 +229,7 @@ void main() {
expect(didTap, isTrue);
}, variant: buttonVariant);
testWidgets('Only container', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Only container', (WidgetTester tester) async {
bool didTap = false;
await tester.pumpWidget(
Center(
......@@ -251,7 +252,7 @@ void main() {
expect(didTap, isFalse);
}, variant: buttonVariant);
testWidgets('cache render object', (WidgetTester tester) async {
testWidgetsWithLeakTracking('cache render object', (WidgetTester tester) async {
void inputCallback() { }
await tester.pumpWidget(
......@@ -283,7 +284,7 @@ void main() {
expect(renderObj1, same(renderObj2));
}, variant: buttonVariant);
testWidgets('Tap down occurs after kPressTimeout', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Tap down occurs after kPressTimeout', (WidgetTester tester) async {
int tapDown = 0;
int tap = 0;
int tapCancel = 0;
......@@ -391,7 +392,7 @@ void main() {
expect(longPress, 1);
}, variant: buttonVariant);
testWidgets('Long Press Up Callback called after long press', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Long Press Up Callback called after long press', (WidgetTester tester) async {
int longPressUp = 0;
await tester.pumpWidget(
......@@ -441,7 +442,7 @@ void main() {
}, variant: buttonVariant);
});
testWidgets('Primary and secondary long press callbacks should work together in GestureDetector', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Primary and secondary long press callbacks should work together in GestureDetector', (WidgetTester tester) async {
bool primaryLongPress = false, secondaryLongPress = false;
await tester.pumpWidget(
......@@ -477,7 +478,7 @@ void main() {
expect(secondaryLongPress, isTrue);
});
testWidgets('Force Press Callback called after force press', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Force Press Callback called after force press', (WidgetTester tester) async {
int forcePressStart = 0;
int forcePressPeaked = 0;
int forcePressUpdate = 0;
......@@ -580,7 +581,7 @@ void main() {
expect(forcePressEnded, 1);
});
testWidgets('Force Press Callback not called if long press triggered before force press', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Force Press Callback not called if long press triggered before force press', (WidgetTester tester) async {
int forcePressStart = 0;
int longPressTimes = 0;
......@@ -645,7 +646,7 @@ void main() {
expect(forcePressStart, 0);
});
testWidgets('Force Press Callback not called if drag triggered before force press', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Force Press Callback not called if drag triggered before force press', (WidgetTester tester) async {
int forcePressStart = 0;
int horizontalDragStart = 0;
......@@ -706,7 +707,7 @@ void main() {
});
group("RawGestureDetectorState's debugFillProperties", () {
testWidgets('when default', (WidgetTester tester) async {
testWidgetsWithLeakTracking('when default', (WidgetTester tester) async {
final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder();
final GlobalKey key = GlobalKey();
await tester.pumpWidget(RawGestureDetector(
......@@ -724,7 +725,7 @@ void main() {
]);
});
testWidgets('should show gestures, custom semantics and behavior', (WidgetTester tester) async {
testWidgetsWithLeakTracking('should show gestures, custom semantics and behavior', (WidgetTester tester) async {
final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder();
final GlobalKey key = GlobalKey();
await tester.pumpWidget(RawGestureDetector(
......@@ -761,7 +762,7 @@ void main() {
]);
});
testWidgets('should not show semantics when excludeFromSemantics is true', (WidgetTester tester) async {
testWidgetsWithLeakTracking('should not show semantics when excludeFromSemantics is true', (WidgetTester tester) async {
final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder();
final GlobalKey key = GlobalKey();
await tester.pumpWidget(RawGestureDetector(
......@@ -832,7 +833,7 @@ void main() {
}
});
testWidgets('replaceGestureRecognizers not during layout', (WidgetTester tester) async {
testWidgetsWithLeakTracking('replaceGestureRecognizers not during layout', (WidgetTester tester) async {
final GlobalKey<RawGestureDetectorState> key = GlobalKey<RawGestureDetectorState>();
await tester.pumpWidget(
Directionality(
......@@ -876,7 +877,7 @@ void main() {
});
});
testWidgets('supportedDevices update test', (WidgetTester tester) async {
testWidgetsWithLeakTracking('supportedDevices update test', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/111716
bool didStartPan = false;
Offset? panDelta;
......@@ -946,7 +947,7 @@ void main() {
expect(didEndPan, isTrue);
});
testWidgets('supportedDevices is respected', (WidgetTester tester) async {
testWidgetsWithLeakTracking('supportedDevices is respected', (WidgetTester tester) async {
bool didStartPan = false;
Offset? panDelta;
bool didEndPan = false;
......@@ -994,7 +995,7 @@ void main() {
});
group('DoubleTap', () {
testWidgets('onDoubleTap is called even if onDoubleTapDown has not been not provided', (WidgetTester tester) async {
testWidgetsWithLeakTracking('onDoubleTap is called even if onDoubleTapDown has not been not provided', (WidgetTester tester) async {
final List<String> log = <String>[];
await tester.pumpWidget(
Directionality(
......@@ -1017,7 +1018,7 @@ void main() {
expect(log, <String>['double-tap']);
});
testWidgets('onDoubleTapDown is called even if onDoubleTap has not been not provided', (WidgetTester tester) async {
testWidgetsWithLeakTracking('onDoubleTapDown is called even if onDoubleTap has not been not provided', (WidgetTester tester) async {
final List<String> log = <String>[];
await tester.pumpWidget(
Directionality(
......
......@@ -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('onTap detection with canceled pointer and a drag listener', (WidgetTester tester) async {
testWidgetsWithLeakTracking('onTap detection with canceled pointer and a drag listener', (WidgetTester tester) async {
int detector1TapCount = 0;
int detector2TapCount = 0;
......
......@@ -5,11 +5,12 @@
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';
// There's also some duplicate GlobalKey tests in the framework_test.dart file.
void main() {
testWidgets('GlobalKey children of one node', (WidgetTester tester) async {
testWidgetsWithLeakTracking('GlobalKey children of one node', (WidgetTester tester) async {
// This is actually a test of the regular duplicate key logic, which
// happens before the duplicate GlobalKey logic.
await tester.pumpWidget(const Stack(children: <Widget>[
......@@ -23,7 +24,7 @@ void main() {
expect(error.toString(), contains('[GlobalObjectKey ${describeIdentity(0)}]'));
});
testWidgets('GlobalKey children of two nodes - A', (WidgetTester tester) async {
testWidgetsWithLeakTracking('GlobalKey children of two nodes - A', (WidgetTester tester) async {
await tester.pumpWidget(const Stack(
textDirection: TextDirection.ltr,
children: <Widget>[
......@@ -43,7 +44,7 @@ void main() {
expect(error.toString(), endsWith('\nA GlobalKey can only be specified on one widget at a time in the widget tree.'));
});
testWidgets('GlobalKey children of two different nodes - B', (WidgetTester tester) async {
testWidgetsWithLeakTracking('GlobalKey children of two different nodes - B', (WidgetTester tester) async {
await tester.pumpWidget(const Stack(
textDirection: TextDirection.ltr,
children: <Widget>[
......@@ -61,7 +62,7 @@ void main() {
expect(error.toString(), endsWith('\nA GlobalKey can only be specified on one widget at a time in the widget tree.'));
});
testWidgets('GlobalKey children of two nodes - C', (WidgetTester tester) async {
testWidgetsWithLeakTracking('GlobalKey children of two nodes - C', (WidgetTester tester) async {
late StateSetter nestedSetState;
bool flag = false;
await tester.pumpWidget(Stack(
......
......@@ -4,6 +4,7 @@
import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
class Item {
GlobalKey key1 = GlobalKey();
......@@ -55,7 +56,7 @@ Widget builder() {
}
void main() {
testWidgets('moving subtrees with global keys - smoketest', (WidgetTester tester) async {
testWidgetsWithLeakTracking('moving subtrees with global keys - smoketest', (WidgetTester tester) async {
await tester.pumpWidget(builder());
final StatefulLeafState leaf = tester.firstState(find.byType(StatefulLeaf));
leaf.markNeedsBuild();
......
......@@ -5,9 +5,10 @@
import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
void main() {
testWidgets('GridPaper control test', (WidgetTester tester) async {
testWidgetsWithLeakTracking('GridPaper control test', (WidgetTester tester) async {
await tester.pumpWidget(const GridPaper());
final List<Layer> layers1 = tester.layers;
await tester.pumpWidget(const GridPaper());
......
......@@ -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('Empty GridView', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Empty GridView', (WidgetTester tester) async {
final List<Widget> children = <Widget>[
const DecoratedBox(decoration: BoxDecoration()),
const DecoratedBox(decoration: BoxDecoration()),
......
......@@ -6,13 +6,14 @@ import 'package:flutter/gestures.dart' show DragStartBehavior;
import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
import '../rendering/rendering_tester.dart' show TestClipPaintingContext;
import 'states.dart';
void main() {
// Regression test for https://github.com/flutter/flutter/issues/100451
testWidgets('GridView.builder respects findChildIndexCallback', (WidgetTester tester) async {
testWidgetsWithLeakTracking('GridView.builder respects findChildIndexCallback', (WidgetTester tester) async {
bool finderCalled = false;
int itemCount = 7;
late StateSetter stateSetter;
......@@ -50,7 +51,7 @@ void main() {
expect(finderCalled, true);
});
testWidgets('Empty GridView', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Empty GridView', (WidgetTester tester) async {
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
......@@ -62,7 +63,7 @@ void main() {
);
});
testWidgets('GridView.count control test', (WidgetTester tester) async {
testWidgetsWithLeakTracking('GridView.count control test', (WidgetTester tester) async {
final List<String> log = <String>[];
await tester.pumpWidget(
......@@ -135,7 +136,7 @@ void main() {
log.clear();
});
testWidgets('GridView.extent control test', (WidgetTester tester) async {
testWidgetsWithLeakTracking('GridView.extent control test', (WidgetTester tester) async {
final List<String> log = <String>[];
await tester.pumpWidget(
......@@ -182,7 +183,7 @@ void main() {
log.clear();
});
testWidgets('GridView large scroll jump', (WidgetTester tester) async {
testWidgetsWithLeakTracking('GridView large scroll jump', (WidgetTester tester) async {
final List<int> log = <int>[];
await tester.pumpWidget(
......@@ -274,7 +275,7 @@ void main() {
}
});
testWidgets('GridView - change crossAxisCount', (WidgetTester tester) async {
testWidgetsWithLeakTracking('GridView - change crossAxisCount', (WidgetTester tester) async {
final List<int> log = <int>[];
await tester.pumpWidget(
......@@ -345,7 +346,7 @@ void main() {
expect(find.text('4'), findsNothing);
});
testWidgets('SliverGridRegularTileLayout - can handle close to zero mainAxisStride', (WidgetTester tester) async {
testWidgetsWithLeakTracking('SliverGridRegularTileLayout - can handle close to zero mainAxisStride', (WidgetTester tester) async {
const SliverGridDelegateWithMaxCrossAxisExtent delegate = SliverGridDelegateWithMaxCrossAxisExtent(
childAspectRatio: 1e300,
maxCrossAxisExtent: 500.0,
......@@ -369,7 +370,7 @@ void main() {
expect(layout.getMinChildIndexForScrollOffset(1000.0), 0.0);
});
testWidgets('GridView - change maxChildCrossAxisExtent', (WidgetTester tester) async {
testWidgetsWithLeakTracking('GridView - change maxChildCrossAxisExtent', (WidgetTester tester) async {
final List<int> log = <int>[];
await tester.pumpWidget(
......@@ -440,7 +441,7 @@ void main() {
expect(find.text('4'), findsNothing);
});
testWidgets('One-line GridView paints', (WidgetTester tester) async {
testWidgetsWithLeakTracking('One-line GridView paints', (WidgetTester tester) async {
const Color green = Color(0xFF00FF00);
final Container container = Container(
......@@ -469,7 +470,7 @@ void main() {
expect(find.byType(GridView), isNot(paints..rect(color: green)..rect(color: green)..rect(color: green)));
});
testWidgets('GridView in zero context', (WidgetTester tester) async {
testWidgetsWithLeakTracking('GridView in zero context', (WidgetTester tester) async {
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
......@@ -490,7 +491,7 @@ void main() {
expect(find.text('1'), findsNothing);
});
testWidgets('GridView in unbounded context', (WidgetTester tester) async {
testWidgetsWithLeakTracking('GridView in unbounded context', (WidgetTester tester) async {
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
......@@ -510,7 +511,7 @@ void main() {
expect(find.text('19'), findsOneWidget);
});
testWidgets('GridView.builder control test', (WidgetTester tester) async {
testWidgetsWithLeakTracking('GridView.builder control test', (WidgetTester tester) async {
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
......@@ -531,7 +532,7 @@ void main() {
expect(find.text('12'), findsNothing);
});
testWidgets('GridView.builder with undefined itemCount', (WidgetTester tester) async {
testWidgetsWithLeakTracking('GridView.builder with undefined itemCount', (WidgetTester tester) async {
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
......@@ -553,7 +554,7 @@ void main() {
expect(find.text('13'), findsOneWidget);
});
testWidgets('GridView cross axis layout', (WidgetTester tester) async {
testWidgetsWithLeakTracking('GridView cross axis layout', (WidgetTester tester) async {
final Key target = UniqueKey();
Widget build(TextDirection textDirection) {
......@@ -579,7 +580,7 @@ void main() {
expect(tester.getBottomRight(find.byKey(target)), const Offset(800.0, 200.0));
});
testWidgets('GridView crossAxisSpacing', (WidgetTester tester) async {
testWidgetsWithLeakTracking('GridView crossAxisSpacing', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/27151.
final Key target = UniqueKey();
......@@ -607,7 +608,7 @@ void main() {
expect(tester.getBottomRight(find.byKey(target)), const Offset(800.0, 194.0));
});
testWidgets('GridView does not cache itemBuilder calls', (WidgetTester tester) async {
testWidgetsWithLeakTracking('GridView does not cache itemBuilder calls', (WidgetTester tester) async {
final Map<int, int> counters = <int, int>{};
await tester.pumpWidget(Directionality(
......@@ -642,7 +643,7 @@ void main() {
expect(counters[4], 2);
});
testWidgets('GridView does not report visual overflow unnecessarily', (WidgetTester tester) async {
testWidgetsWithLeakTracking('GridView does not report visual overflow unnecessarily', (WidgetTester tester) async {
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
......@@ -663,9 +664,18 @@ void main() {
final TestClipPaintingContext context = TestClipPaintingContext();
renderObject.paint(context, Offset.zero);
expect(context.clipBehavior, equals(Clip.none));
});
},
leakTrackingTestConfig: const LeakTrackingTestConfig(
// TODO(ksokolovskyi): remove after fixing
notDisposedAllowList: <String, int?> {
// https://github.com/flutter/flutter/issues/134575
'OffsetLayer': 1,
// https://github.com/flutter/flutter/issues/134572
'ContainerLayer': 1,
},
));
testWidgets('GridView respects clipBehavior', (WidgetTester tester) async {
testWidgetsWithLeakTracking('GridView respects clipBehavior', (WidgetTester tester) async {
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
......@@ -729,9 +739,14 @@ void main() {
// 4th, check that a non-default clip behavior can be sent to the painting context.
renderObject.paint(context, Offset.zero);
expect(context.clipBehavior, equals(Clip.antiAlias));
});
},
leakTrackingTestConfig: const LeakTrackingTestConfig(
// TODO(ksokolovskyi): remove after fixing
// https://github.com/flutter/flutter/issues/134572
notDisposedAllowList: <String, int?> {'ContainerLayer': 1},
));
testWidgets('GridView.builder respects clipBehavior', (WidgetTester tester) async {
testWidgetsWithLeakTracking('GridView.builder respects clipBehavior', (WidgetTester tester) async {
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
......@@ -747,7 +762,7 @@ void main() {
expect(renderObject.clipBehavior, equals(Clip.antiAlias));
});
testWidgets('GridView.custom respects clipBehavior', (WidgetTester tester) async {
testWidgetsWithLeakTracking('GridView.custom respects clipBehavior', (WidgetTester tester) async {
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
......@@ -765,7 +780,7 @@ void main() {
expect(renderObject.clipBehavior, equals(Clip.antiAlias));
});
testWidgets('GridView.count respects clipBehavior', (WidgetTester tester) async {
testWidgetsWithLeakTracking('GridView.count respects clipBehavior', (WidgetTester tester) async {
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
......@@ -780,7 +795,7 @@ void main() {
expect(renderObject.clipBehavior, equals(Clip.antiAlias));
});
testWidgets('GridView.extent respects clipBehavior', (WidgetTester tester) async {
testWidgetsWithLeakTracking('GridView.extent respects clipBehavior', (WidgetTester tester) async {
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
......@@ -795,7 +810,7 @@ void main() {
expect(renderObject.clipBehavior, equals(Clip.antiAlias));
});
testWidgets('SliverGridDelegateWithFixedCrossAxisCount mainAxisExtent works as expected', (WidgetTester tester) async {
testWidgetsWithLeakTracking('SliverGridDelegateWithFixedCrossAxisCount mainAxisExtent works as expected', (WidgetTester tester) async {
const int crossAxisCount = 4;
const double mainAxisExtent = 100.0;
......@@ -821,7 +836,7 @@ void main() {
expect(tester.getSize(find.text('4')), equals(const Size(200.0, mainAxisExtent)));
});
testWidgets('SliverGridDelegateWithMaxCrossAxisExtent mainAxisExtent works as expected', (WidgetTester tester) async {
testWidgetsWithLeakTracking('SliverGridDelegateWithMaxCrossAxisExtent mainAxisExtent works as expected', (WidgetTester tester) async {
const double maxCrossAxisExtent = 200.0;
const double mainAxisExtent = 100.0;
......@@ -847,7 +862,7 @@ void main() {
expect(tester.getSize(find.text('4')), equals(const Size(200.0, mainAxisExtent)));
});
testWidgets('SliverGridDelegateWithMaxCrossAxisExtent throws assertion error when maxCrossAxisExtent is 0', (WidgetTester tester) async {
testWidgetsWithLeakTracking('SliverGridDelegateWithMaxCrossAxisExtent throws assertion error when maxCrossAxisExtent is 0', (WidgetTester tester) async {
const double maxCrossAxisExtent = 0;
expect(() => Directionality(
......@@ -858,9 +873,10 @@ void main() {
), throwsAssertionError);
});
testWidgets('SliverGrid sets correct extent for null returning builder delegate', (WidgetTester tester) async {
testWidgetsWithLeakTracking('SliverGrid sets correct extent for null returning builder delegate', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/130685
final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
await tester.pumpWidget(Directionality(
textDirection: TextDirection.ltr,
child: GridView.builder(
......
......@@ -9,6 +9,7 @@ import 'package:flutter/foundation.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 '../painting/image_test_utils.dart' show TestImageProvider;
......@@ -190,7 +191,7 @@ Future<void> main() async {
transitionFromUserGestures = false;
});
testWidgets('Heroes animate', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Heroes animate', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(routes: routes));
......@@ -300,7 +301,7 @@ Future<void> main() async {
expect(find.byKey(thirdKey), isInCard);
});
testWidgets('Heroes still animate after hero controller is swapped.', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Heroes still animate after hero controller is swapped.', (WidgetTester tester) async {
final GlobalKey<NavigatorState> key = GlobalKey<NavigatorState>();
final UniqueKey heroKey = UniqueKey();
await tester.pumpWidget(
......@@ -395,7 +396,7 @@ Future<void> main() async {
expect(find.byKey(heroKey), findsNothing);
});
testWidgets('Heroes animate should hide original hero', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Heroes animate should hide original hero', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(routes: routes));
// Checks initial state.
expect(find.byKey(firstKey), isOnstage);
......@@ -418,7 +419,7 @@ Future<void> main() async {
expect(find.byKey(secondKey), isInCard);
});
testWidgets('Destination hero is rebuilt midflight', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Destination hero is rebuilt midflight', (WidgetTester tester) async {
final MutatingRoute route = MutatingRoute();
await tester.pumpWidget(MaterialApp(
......@@ -443,7 +444,7 @@ Future<void> main() async {
await tester.pump(const Duration(seconds: 1));
});
testWidgets('Heroes animation is fastOutSlowIn', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Heroes animation is fastOutSlowIn', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(routes: routes));
await tester.tap(find.text('two'));
await tester.pump(); // begin navigation
......@@ -483,7 +484,7 @@ Future<void> main() async {
);
});
testWidgets('Heroes are not interactive', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Heroes are not interactive', (WidgetTester tester) async {
final List<String> log = <String>[];
await tester.pumpWidget(MaterialApp(
......@@ -553,7 +554,7 @@ Future<void> main() async {
expect(log, equals(<String>['bar']));
});
testWidgets('Popping on first frame does not cause hero observer to crash', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Popping on first frame does not cause hero observer to crash', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(
onGenerateRoute: (RouteSettings settings) {
return MaterialPageRoute<void>(
......@@ -574,7 +575,7 @@ Future<void> main() async {
await tester.pump(); // ...and removes it straight away (since it's already at 0.0)
});
testWidgets('Overlapping starting and ending a hero transition works ok', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Overlapping starting and ending a hero transition works ok', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(
onGenerateRoute: (RouteSettings settings) {
return MaterialPageRoute<void>(
......@@ -603,7 +604,7 @@ Future<void> main() async {
await tester.pump();
});
testWidgets('One route, two heroes, same tag, throws', (WidgetTester tester) async {
testWidgetsWithLeakTracking('One route, two heroes, same tag, throws', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(
home: Material(
child: ListView(
......@@ -658,7 +659,7 @@ Future<void> main() async {
);
});
testWidgets('Hero push transition interrupted by a pop', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Hero push transition interrupted by a pop', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(
routes: routes,
));
......@@ -723,7 +724,7 @@ Future<void> main() async {
expect(find.byKey(secondKey), findsNothing);
});
testWidgets('Hero pop transition interrupted by a push', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Hero pop transition interrupted by a push', (WidgetTester tester) async {
await tester.pumpWidget(
MaterialApp(
routes: routes,
......@@ -800,7 +801,7 @@ Future<void> main() async {
expect(find.byKey(firstKey), findsNothing);
});
testWidgets('Destination hero disappears mid-flight', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Destination hero disappears mid-flight', (WidgetTester tester) async {
const Key homeHeroKey = Key('home hero');
const Key routeHeroKey = Key('route hero');
bool routeIncludesHero = true;
......@@ -903,7 +904,7 @@ Future<void> main() async {
});
testWidgets('Destination hero scrolls mid-flight', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Destination hero scrolls mid-flight', (WidgetTester tester) async {
const Key homeHeroKey = Key('home hero');
const Key routeHeroKey = Key('route hero');
const Key routeContainerKey = Key('route hero container');
......@@ -990,7 +991,7 @@ Future<void> main() async {
expect(finalHeroY, 75.0); // 100 less 25 for the scroll
});
testWidgets('Destination hero scrolls out of view mid-flight', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Destination hero scrolls out of view mid-flight', (WidgetTester tester) async {
const Key homeHeroKey = Key('home hero');
const Key routeHeroKey = Key('route hero');
const Key routeContainerKey = Key('route hero container');
......@@ -1067,7 +1068,7 @@ Future<void> main() async {
expect(find.byKey(routeHeroKey), findsNothing);
});
testWidgets('Aborted flight', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Aborted flight', (WidgetTester tester) async {
// See https://github.com/flutter/flutter/issues/5798
const Key heroABKey = Key('AB hero');
const Key heroBCKey = Key('BC hero');
......@@ -1202,7 +1203,7 @@ Future<void> main() async {
expect(tester.getTopLeft(find.byKey(heroBCKey)).dy, 0.0);
});
testWidgets('Stateful hero child state survives flight', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Stateful hero child state survives flight', (WidgetTester tester) async {
final MaterialPageRoute<void> route = MaterialPageRoute<void>(
builder: (BuildContext context) {
return Material(
......@@ -1286,7 +1287,7 @@ Future<void> main() async {
});
testWidgets('Hero createRectTween', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Hero createRectTween', (WidgetTester tester) async {
RectTween createRectTween(Rect? begin, Rect? end) {
return MaterialRectCenterArcTween(begin: begin, end: end);
}
......@@ -1398,7 +1399,7 @@ Future<void> main() async {
expect(tester.getCenter(find.byKey(firstKey)), const Offset(50.0, 50.0));
});
testWidgets('Hero createRectTween for Navigator that is not full screen', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Hero createRectTween for Navigator that is not full screen', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/25272
RectTween createRectTween(Rect? begin, Rect? end) {
......@@ -1519,7 +1520,7 @@ Future<void> main() async {
});
testWidgets('Pop interrupts push, reverses flight', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Pop interrupts push, reverses flight', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(routes: routes));
await tester.tap(find.text('twoInset'));
await tester.pump(); // begin navigation from / to /twoInset.
......@@ -1612,7 +1613,7 @@ Future<void> main() async {
expect(tester.getTopLeft(find.byKey(firstKey)).dx, x0);
});
testWidgets('Can override flight shuttle in to hero', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Can override flight shuttle in to hero', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(
home: Material(
child: ListView(
......@@ -1656,7 +1657,7 @@ Future<void> main() async {
expect(find.text('baz'), findsOneWidget);
});
testWidgets('Can override flight shuttle in from hero', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Can override flight shuttle in from hero', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(
home: Material(
child: ListView(
......@@ -1699,7 +1700,7 @@ Future<void> main() async {
});
// Regression test for https://github.com/flutter/flutter/issues/77720.
testWidgets("toHero's shuttle builder over fromHero's shuttle builder", (WidgetTester tester) async {
testWidgetsWithLeakTracking("toHero's shuttle builder over fromHero's shuttle builder", (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(
home: Material(
child: ListView(
......@@ -1752,7 +1753,7 @@ Future<void> main() async {
expect(find.text('toHero text'), findsOneWidget);
});
testWidgets('Can override flight launch pads', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Can override flight launch pads', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(
home: Material(
child: ListView(
......@@ -1799,7 +1800,7 @@ Future<void> main() async {
expect(find.text('Joker'), findsOneWidget);
});
testWidgets('Heroes do not transition on back gestures by default', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Heroes do not transition on back gestures by default', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(
routes: routes,
));
......@@ -1838,7 +1839,7 @@ Future<void> main() async {
expect(find.byKey(secondKey), isInCard);
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
testWidgets('Heroes can transition on gesture in one frame', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Heroes can transition on gesture in one frame', (WidgetTester tester) async {
transitionFromUserGestures = true;
await tester.pumpWidget(MaterialApp(
routes: routes,
......@@ -1881,7 +1882,7 @@ Future<void> main() async {
expect(find.byKey(secondKey), findsNothing);
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
testWidgets('Heroes animate should hide destination hero and display original hero in case of dismissed', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Heroes animate should hide destination hero and display original hero in case of dismissed', (WidgetTester tester) async {
transitionFromUserGestures = true;
await tester.pumpWidget(MaterialApp(
routes: routes,
......@@ -1917,7 +1918,7 @@ Future<void> main() async {
expect(find.byKey(secondKey), isInCard);
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
testWidgets('Handles transitions when a non-default initial route is set', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Handles transitions when a non-default initial route is set', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(
routes: routes,
initialRoute: '/two',
......@@ -1927,7 +1928,7 @@ Future<void> main() async {
expect(find.text('three'), findsOneWidget);
});
testWidgets('Can push/pop on outer Navigator if nested Navigator contains Heroes', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Can push/pop on outer Navigator if nested Navigator contains Heroes', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/28042.
const String heroTag = 'You are my hero!';
......@@ -2001,7 +2002,7 @@ Future<void> main() async {
expect(find.byKey(nestedRouteHeroBottom, skipOffstage: false), findsOneWidget);
});
testWidgets('Can hero from route in root Navigator to route in nested Navigator', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Can hero from route in root Navigator to route in nested Navigator', (WidgetTester tester) async {
const String heroTag = 'foo';
final GlobalKey<NavigatorState> rootNavigator = GlobalKey();
final Key smallContainer = UniqueKey();
......@@ -2087,7 +2088,7 @@ Future<void> main() async {
expect(tester.getSize(find.byKey(smallContainer)), const Size(100,100));
});
testWidgets('Hero within a Hero, throws', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Hero within a Hero, throws', (WidgetTester tester) async {
await tester.pumpWidget(
const MaterialApp(
home: Material(
......@@ -2105,7 +2106,7 @@ Future<void> main() async {
expect(tester.takeException(), isAssertionError);
});
testWidgets('Can push/pop on outer Navigator if nested Navigators contains same Heroes', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Can push/pop on outer Navigator if nested Navigators contains same Heroes', (WidgetTester tester) async {
const String heroTag = 'foo';
final GlobalKey<NavigatorState> rootNavigator = GlobalKey<NavigatorState>();
final Key rootRouteHero = UniqueKey();
......@@ -2189,7 +2190,7 @@ Future<void> main() async {
expect(find.byKey(nestedRouteHeroOne, skipOffstage: false), findsOneWidget);
});
testWidgets('Hero within a Hero subtree, throws', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Hero within a Hero subtree, throws', (WidgetTester tester) async {
await tester.pumpWidget(
const MaterialApp(
home: Material(
......@@ -2207,7 +2208,7 @@ Future<void> main() async {
expect(tester.takeException(), isAssertionError);
});
testWidgets('Hero within a Hero subtree with Builder, throws', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Hero within a Hero subtree with Builder, throws', (WidgetTester tester) async {
await tester.pumpWidget(
MaterialApp(
home: Material(
......@@ -2229,7 +2230,7 @@ Future<void> main() async {
expect(tester.takeException(),isAssertionError);
});
testWidgets('Hero within a Hero subtree with LayoutBuilder, throws', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Hero within a Hero subtree with LayoutBuilder, throws', (WidgetTester tester) async {
await tester.pumpWidget(
MaterialApp(
home: Material(
......@@ -2251,7 +2252,7 @@ Future<void> main() async {
expect(tester.takeException(), isAssertionError);
});
testWidgets('Heroes fly on pushReplacement', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Heroes fly on pushReplacement', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/28041.
const String heroTag = 'foo';
......@@ -2338,7 +2339,7 @@ Future<void> main() async {
expect(tester.getSize(find.byKey(smallContainer)), const Size(100,100));
});
testWidgets('On an iOS back swipe and snap, only a single flight should take place', (WidgetTester tester) async {
testWidgetsWithLeakTracking('On an iOS back swipe and snap, only a single flight should take place', (WidgetTester tester) async {
int shuttlesBuilt = 0;
Widget shuttleBuilder(
BuildContext flightContext,
......@@ -2401,7 +2402,7 @@ Future<void> main() async {
expect(shuttlesBuilt, 2);
});
testWidgets(
testWidgetsWithLeakTracking(
"From hero's state should be preserved, "
'heroes work well with child widgets that has global keys',
(WidgetTester tester) async {
......@@ -2468,7 +2469,7 @@ Future<void> main() async {
},
);
testWidgets(
testWidgetsWithLeakTracking(
"Hero works with images that don't have both width and height specified",
// Regression test for https://github.com/flutter/flutter/issues/32356
// and https://github.com/flutter/flutter/issues/31503
......@@ -2556,7 +2557,7 @@ Future<void> main() async {
);
// Regression test for https://github.com/flutter/flutter/issues/38183.
testWidgets('Remove user gesture driven flights when the gesture is invalid', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Remove user gesture driven flights when the gesture is invalid', (WidgetTester tester) async {
transitionFromUserGestures = true;
await tester.pumpWidget(MaterialApp(
routes: routes,
......@@ -2585,7 +2586,7 @@ Future<void> main() async {
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
// Regression test for https://github.com/flutter/flutter/issues/40239.
testWidgets(
testWidgetsWithLeakTracking(
'In a pop transition, when fromHero is null, the to hero should eventually become visible',
(WidgetTester tester) async {
final GlobalKey<NavigatorState> navigatorKey = GlobalKey();
......@@ -2634,7 +2635,7 @@ Future<void> main() async {
},
);
testWidgets('popped hero uses fastOutSlowIn curve', (WidgetTester tester) async {
testWidgetsWithLeakTracking('popped hero uses fastOutSlowIn curve', (WidgetTester tester) async {
final Key container1 = UniqueKey();
final Key container2 = UniqueKey();
final GlobalKey<NavigatorState> navigator = GlobalKey<NavigatorState>();
......@@ -2712,7 +2713,7 @@ Future<void> main() async {
expect(heroSize, tween.transform(1.0));
});
testWidgets('Heroes in enabled HeroMode do transition', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Heroes in enabled HeroMode do transition', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(
home: Material(
child: Column(
......@@ -2783,7 +2784,7 @@ Future<void> main() async {
expect(find.byKey(secondKey), isInCard);
});
testWidgets('Heroes in disabled HeroMode do not transition', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Heroes in disabled HeroMode do not transition', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(
home: Material(
child: Column(
......@@ -2861,7 +2862,7 @@ Future<void> main() async {
expect(find.byKey(secondKey), isOnstage);
});
testWidgets('kept alive Hero does not throw when the transition begins', (WidgetTester tester) async {
testWidgetsWithLeakTracking('kept alive Hero does not throw when the transition begins', (WidgetTester tester) async {
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
await tester.pumpWidget(
......@@ -2914,9 +2915,10 @@ Future<void> main() async {
expect(find.byType(Placeholder), findsOneWidget);
});
testWidgets('toHero becomes unpaintable after the transition begins', (WidgetTester tester) async {
testWidgetsWithLeakTracking('toHero becomes unpaintable after the transition begins', (WidgetTester tester) async {
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
RenderAnimatedOpacity? findRenderAnimatedOpacity() {
RenderObject? parent = tester.renderObject(find.byType(Placeholder));
......@@ -2989,7 +2991,7 @@ Future<void> main() async {
expect(find.byType(Placeholder), findsNothing);
});
testWidgets('diverting to a keepalive but unpaintable hero', (WidgetTester tester) async {
testWidgetsWithLeakTracking('diverting to a keepalive but unpaintable hero', (WidgetTester tester) async {
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
await tester.pumpWidget(
......@@ -3069,7 +3071,7 @@ Future<void> main() async {
expect(tester.takeException(), isNull);
});
testWidgets('smooth transition between different incoming data', (WidgetTester tester) async {
testWidgetsWithLeakTracking('smooth transition between different incoming data', (WidgetTester tester) async {
addTearDown(tester.view.reset);
final GlobalKey<NavigatorState> navigatorKey = GlobalKey();
......
......@@ -6,16 +6,17 @@ import 'package:flutter/gestures.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';
void main() {
testWidgets('toString control test', (WidgetTester tester) async {
testWidgetsWithLeakTracking('toString control test', (WidgetTester tester) async {
await tester.pumpWidget(const Center(child: Text('Hello', textDirection: TextDirection.ltr)));
final HitTestResult result = tester.hitTestOnBinding(Offset.zero);
expect(result, hasOneLineDescription);
expect(result.path.first, hasOneLineDescription);
});
testWidgets('A mouse click should only cause one hit test', (WidgetTester tester) async {
testWidgetsWithLeakTracking('A mouse click should only cause one hit test', (WidgetTester tester) async {
int hitCount = 0;
await tester.pumpWidget(
_HitTestCounter(
......@@ -31,7 +32,7 @@ void main() {
expect(hitCount, 1);
});
testWidgets('Non-mouse events should not cause movement hit tests', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Non-mouse events should not cause movement hit tests', (WidgetTester tester) async {
int hitCount = 0;
await tester.pumpWidget(
_HitTestCounter(
......
......@@ -5,9 +5,10 @@
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';
void main() {
testWidgets('Can tap a hyperlink', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Can tap a hyperlink', (WidgetTester tester) async {
bool didTapLeft = false;
final TapGestureRecognizer tapLeft = TapGestureRecognizer()
..onTap = () {
......
......@@ -6,11 +6,12 @@ import 'dart:ui';
import 'package:flutter/material.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('Can set opacity for an Icon', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Can set opacity for an Icon', (WidgetTester tester) async {
await tester.pumpWidget(
const Directionality(
textDirection: TextDirection.ltr,
......@@ -27,7 +28,7 @@ void main() {
expect(text.text.style!.color, const Color(0xFF666666).withOpacity(0.5));
});
testWidgets('Icon sizing - no theme, default size', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Icon sizing - no theme, default size', (WidgetTester tester) async {
await tester.pumpWidget(
const Directionality(
textDirection: TextDirection.ltr,
......@@ -41,7 +42,7 @@ void main() {
expect(renderObject.size, equals(const Size.square(24.0)));
});
testWidgets('Icon sizing - no theme, explicit size', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Icon sizing - no theme, explicit size', (WidgetTester tester) async {
await tester.pumpWidget(
const Directionality(
textDirection: TextDirection.ltr,
......@@ -58,7 +59,7 @@ void main() {
expect(renderObject.size, equals(const Size.square(96.0)));
});
testWidgets('Icon sizing - sized theme', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Icon sizing - sized theme', (WidgetTester tester) async {
await tester.pumpWidget(
const Directionality(
textDirection: TextDirection.ltr,
......@@ -75,7 +76,7 @@ void main() {
expect(renderObject.size, equals(const Size.square(36.0)));
});
testWidgets('Icon sizing - sized theme, explicit size', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Icon sizing - sized theme, explicit size', (WidgetTester tester) async {
await tester.pumpWidget(
const Directionality(
textDirection: TextDirection.ltr,
......@@ -95,7 +96,7 @@ void main() {
expect(renderObject.size, equals(const Size.square(48.0)));
});
testWidgets('Icon sizing - sizeless theme, default size', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Icon sizing - sizeless theme, default size', (WidgetTester tester) async {
await tester.pumpWidget(
const Directionality(
textDirection: TextDirection.ltr,
......@@ -113,7 +114,7 @@ void main() {
});
testWidgets('Icon with custom font', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Icon with custom font', (WidgetTester tester) async {
await tester.pumpWidget(
const Directionality(
textDirection: TextDirection.ltr,
......@@ -127,7 +128,7 @@ void main() {
expect(richText.text.style!.fontFamily, equals('Roboto'));
});
testWidgets('Icon with custom fontFamilyFallback', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Icon with custom fontFamilyFallback', (WidgetTester tester) async {
await tester.pumpWidget(
const Directionality(
textDirection: TextDirection.ltr,
......@@ -141,7 +142,7 @@ void main() {
expect(richText.text.style!.fontFamilyFallback, equals(<String>['FallbackFont']));
});
testWidgets('Icon with semantic label', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Icon with semantic label', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester);
await tester.pumpWidget(
......@@ -161,7 +162,7 @@ void main() {
semantics.dispose();
});
testWidgets('Null icon with semantic label', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Null icon with semantic label', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester);
await tester.pumpWidget(
......@@ -181,7 +182,7 @@ void main() {
semantics.dispose();
});
testWidgets("Changing semantic label from null doesn't rebuild tree ", (WidgetTester tester) async {
testWidgetsWithLeakTracking("Changing semantic label from null doesn't rebuild tree ", (WidgetTester tester) async {
await tester.pumpWidget(
const Directionality(
textDirection: TextDirection.ltr,
......@@ -212,7 +213,7 @@ void main() {
expect(richText2, same(richText1));
});
testWidgets('IconData comparison', (WidgetTester tester) async {
testWidgetsWithLeakTracking('IconData comparison', (WidgetTester tester) async {
expect(const IconData(123), const IconData(123));
expect(const IconData(123), isNot(const IconData(123, matchTextDirection: true)));
expect(const IconData(123), isNot(const IconData(123, fontFamily: 'f')));
......@@ -225,7 +226,7 @@ void main() {
});
testWidgets('Fill, weight, grade, and optical size variations are passed', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Fill, weight, grade, and optical size variations are passed', (WidgetTester tester) async {
await tester.pumpWidget(
const Directionality(
textDirection: TextDirection.ltr,
......@@ -258,7 +259,7 @@ void main() {
]);
});
testWidgets('Fill, weight, grade, and optical size can be set at the theme-level', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Fill, weight, grade, and optical size can be set at the theme-level', (WidgetTester tester) async {
await tester.pumpWidget(
const Directionality(
textDirection: TextDirection.ltr,
......@@ -283,7 +284,7 @@ void main() {
]);
});
testWidgets('Theme-level fill, weight, grade, and optical size can be overridden', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Theme-level fill, weight, grade, and optical size can be overridden', (WidgetTester tester) async {
await tester.pumpWidget(
const Directionality(
textDirection: TextDirection.ltr,
......
......@@ -13,17 +13,18 @@ import 'dart:ui' as ui;
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';
void main() {
testWidgets('Image at default filterQuality', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Image at default filterQuality', (WidgetTester tester) async {
await testImageQuality(tester, null);
});
testWidgets('Image at high filterQuality', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Image at high filterQuality', (WidgetTester tester) async {
await testImageQuality(tester, ui.FilterQuality.high);
});
testWidgets('Image at none filterQuality', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Image at none filterQuality', (WidgetTester tester) async {
await testImageQuality(tester, ui.FilterQuality.none);
});
}
......
......@@ -14,9 +14,10 @@ import 'package:flutter/foundation.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('Image filter - blur', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Image filter - blur', (WidgetTester tester) async {
await tester.pumpWidget(
RepaintBoundary(
child: ImageFiltered(
......@@ -31,7 +32,7 @@ void main() {
);
});
testWidgets('Image filter - blur with offset', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Image filter - blur with offset', (WidgetTester tester) async {
final Key key = GlobalKey();
await tester.pumpWidget(
RepaintBoundary(
......@@ -51,7 +52,7 @@ void main() {
);
});
testWidgets('Image filter - dilate', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Image filter - dilate', (WidgetTester tester) async {
await tester.pumpWidget(
RepaintBoundary(
child: ImageFiltered(
......@@ -66,7 +67,7 @@ void main() {
);
}, skip: kIsWeb); // https://github.com/flutter/flutter/issues/101874
testWidgets('Image filter - erode', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Image filter - erode', (WidgetTester tester) async {
await tester.pumpWidget(
RepaintBoundary(
child: ImageFiltered(
......@@ -82,7 +83,7 @@ void main() {
);
}, skip: kIsWeb); // https://github.com/flutter/flutter/issues/101874
testWidgets('Image filter - matrix', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Image filter - matrix', (WidgetTester tester) async {
final ImageFilter matrix = ImageFilter.matrix(Float64List.fromList(<double>[
0.5, 0.0, 0.0, 0.0, //
0.0, 0.5, 0.0, 0.0, //
......@@ -119,7 +120,7 @@ void main() {
);
});
testWidgets('Image filter - matrix with offset', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Image filter - matrix with offset', (WidgetTester tester) async {
final Matrix4 matrix = Matrix4.rotationZ(pi / 18);
final ImageFilter matrixFilter = ImageFilter.matrix(matrix.storage);
final Key key = GlobalKey();
......@@ -157,7 +158,7 @@ void main() {
);
});
testWidgets('Image filter - reuses its layer', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Image filter - reuses its layer', (WidgetTester tester) async {
Future<void> pumpWithSigma(double sigma) async {
await tester.pumpWidget(
RepaintBoundary(
......@@ -178,7 +179,7 @@ void main() {
expect(renderObject.debugLayer, same(originalLayer));
});
testWidgets('Image filter - enabled and disabled', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Image filter - enabled and disabled', (WidgetTester tester) async {
Future<void> pumpWithEnabledState(bool enabled) async {
await tester.pumpWidget(
RepaintBoundary(
......
......@@ -7,13 +7,14 @@ import 'dart:io';
import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
import '../image_data.dart';
void main() {
final MockHttpClient client = MockHttpClient();
testWidgets('Headers', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Headers', (WidgetTester tester) async {
HttpOverrides.runZoned<Future<void>>(() async {
await tester.pumpWidget(Image.network(
'https://www.example.com/images/frame.png',
......
......@@ -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';
import '../painting/mocks_for_image_cache.dart';
......@@ -20,7 +21,7 @@ void main() {
);
});
testWidgets('ImageIcon sizing - no theme, default size', (WidgetTester tester) async {
testWidgetsWithLeakTracking('ImageIcon sizing - no theme, default size', (WidgetTester tester) async {
await tester.pumpWidget(
Center(
child: ImageIcon(image),
......@@ -32,7 +33,7 @@ void main() {
expect(find.byType(Image), findsOneWidget);
});
testWidgets('Icon opacity', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Icon opacity', (WidgetTester tester) async {
await tester.pumpWidget(
Center(
child: IconTheme(
......@@ -45,7 +46,7 @@ void main() {
expect(tester.widget<Image>(find.byType(Image)).color!.alpha, equals(128));
});
testWidgets('ImageIcon sizing - no theme, explicit size', (WidgetTester tester) async {
testWidgetsWithLeakTracking('ImageIcon sizing - no theme, explicit size', (WidgetTester tester) async {
await tester.pumpWidget(
const Center(
child: ImageIcon(
......@@ -59,7 +60,7 @@ void main() {
expect(renderObject.size, equals(const Size.square(96.0)));
});
testWidgets('ImageIcon sizing - sized theme', (WidgetTester tester) async {
testWidgetsWithLeakTracking('ImageIcon sizing - sized theme', (WidgetTester tester) async {
await tester.pumpWidget(
const Center(
child: IconTheme(
......@@ -73,7 +74,7 @@ void main() {
expect(renderObject.size, equals(const Size.square(36.0)));
});
testWidgets('ImageIcon sizing - sized theme, explicit size', (WidgetTester tester) async {
testWidgetsWithLeakTracking('ImageIcon sizing - sized theme, explicit size', (WidgetTester tester) async {
await tester.pumpWidget(
const Center(
child: IconTheme(
......@@ -90,7 +91,7 @@ void main() {
expect(renderObject.size, equals(const Size.square(48.0)));
});
testWidgets('ImageIcon sizing - sizeless theme, default size', (WidgetTester tester) async {
testWidgetsWithLeakTracking('ImageIcon sizing - sizeless theme, default size', (WidgetTester tester) async {
await tester.pumpWidget(
const Center(
child: IconTheme(
......@@ -104,7 +105,7 @@ void main() {
expect(renderObject.size, equals(const Size.square(24.0)));
});
testWidgets('ImageIcon has semantics data', (WidgetTester tester) async {
testWidgetsWithLeakTracking('ImageIcon has semantics data', (WidgetTester tester) async {
final SemanticsHandle handle = tester.ensureSemantics();
await tester.pumpWidget(
const Directionality(
......
......@@ -13,6 +13,7 @@ import 'package:flutter/rendering.dart';
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';
import '../image_data.dart';
......@@ -155,6 +156,7 @@ void main() {
const String image = 'assets/image.png';
final Map<double, ui.Image> images = <double, ui.Image>{};
setUpAll(() async {
for (final double scale in const <double>[0.5, 1.0, 1.5, 2.0, 4.0, 10.0]) {
final int dimension = (48 * scale).floor();
......@@ -162,7 +164,13 @@ void main() {
}
});
testWidgets('Image for device pixel ratio 1.0', (WidgetTester tester) async {
tearDownAll(() {
for (final ui.Image image in images.values) {
image.dispose();
}
});
testWidgetsWithLeakTracking('Image for device pixel ratio 1.0', (WidgetTester tester) async {
const double ratio = 1.0;
Key key = GlobalKey();
await pumpTreeToLayout(tester, buildImageAtRatio(image, key, ratio, false, images));
......@@ -174,7 +182,7 @@ void main() {
expect(getRenderImage(tester, key).scale, 1.0);
});
testWidgets('Image for device pixel ratio 0.5', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Image for device pixel ratio 0.5', (WidgetTester tester) async {
const double ratio = 0.5;
Key key = GlobalKey();
await pumpTreeToLayout(tester, buildImageAtRatio(image, key, ratio, false, images));
......@@ -186,7 +194,7 @@ void main() {
expect(getRenderImage(tester, key).scale, 1.0);
});
testWidgets('Image for device pixel ratio 1.5', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Image for device pixel ratio 1.5', (WidgetTester tester) async {
const double ratio = 1.5;
Key key = GlobalKey();
await pumpTreeToLayout(tester, buildImageAtRatio(image, key, ratio, false, images));
......@@ -201,7 +209,7 @@ void main() {
// A 1.75 DPR screen is typically a low-resolution screen, such that physical
// pixels are visible to the user. For such screens we prefer to pick the
// higher resolution image, if available.
testWidgets('Image for device pixel ratio 1.75', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Image for device pixel ratio 1.75', (WidgetTester tester) async {
const double ratio = 1.75;
Key key = GlobalKey();
await pumpTreeToLayout(tester, buildImageAtRatio(image, key, ratio, false, images));
......@@ -213,7 +221,7 @@ void main() {
expect(getRenderImage(tester, key).scale, 2.0);
});
testWidgets('Image for device pixel ratio 2.3', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Image for device pixel ratio 2.3', (WidgetTester tester) async {
const double ratio = 2.3;
Key key = GlobalKey();
await pumpTreeToLayout(tester, buildImageAtRatio(image, key, ratio, false, images));
......@@ -225,7 +233,7 @@ void main() {
expect(getRenderImage(tester, key).scale, 2.0);
});
testWidgets('Image for device pixel ratio 3.7', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Image for device pixel ratio 3.7', (WidgetTester tester) async {
const double ratio = 3.7;
Key key = GlobalKey();
await pumpTreeToLayout(tester, buildImageAtRatio(image, key, ratio, false, images));
......@@ -237,7 +245,7 @@ void main() {
expect(getRenderImage(tester, key).scale, 4.0);
});
testWidgets('Image for device pixel ratio 5.1', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Image for device pixel ratio 5.1', (WidgetTester tester) async {
const double ratio = 5.1;
Key key = GlobalKey();
await pumpTreeToLayout(tester, buildImageAtRatio(image, key, ratio, false, images));
......@@ -249,7 +257,7 @@ void main() {
expect(getRenderImage(tester, key).scale, 4.0);
});
testWidgets('Image for device pixel ratio 1.0, with a main asset and a 1.0x asset', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Image for device pixel ratio 1.0, with a main asset and a 1.0x asset', (WidgetTester tester) async {
// If both a main asset and a 1.0x asset are specified, then prefer
// the 1.0x asset.
......@@ -279,19 +287,19 @@ void main() {
expect(getRenderImage(tester, key).image!.height, 480);
});
testWidgets('Image cache resize upscale display 5', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Image cache resize upscale display 5', (WidgetTester tester) async {
final Key key = GlobalKey();
await pumpTreeToLayout(tester, buildImageCacheResized(image, key, 5, 5, 20, 20));
expect(getRenderImage(tester, key).size, const Size(5.0, 5.0));
});
testWidgets('Image cache resize upscale display 50', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Image cache resize upscale display 50', (WidgetTester tester) async {
final Key key = GlobalKey();
await pumpTreeToLayout(tester, buildImageCacheResized(image, key, 50, 50, 20, 20));
expect(getRenderImage(tester, key).size, const Size(50.0, 50.0));
});
testWidgets('Image cache resize downscale display 5', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Image cache resize downscale display 5', (WidgetTester tester) async {
final Key key = GlobalKey();
await pumpTreeToLayout(tester, buildImageCacheResized(image, key, 5, 5, 1, 1));
expect(getRenderImage(tester, key).size, const Size(5.0, 5.0));
......@@ -301,7 +309,7 @@ void main() {
// visible physical pixel size (see the test for 1.75 DPR above). However,
// if higher resolution assets are not available we will pick the best
// available.
testWidgets('Low-resolution assets', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Low-resolution assets', (WidgetTester tester) async {
const Map<Object?, Object?> manifest = <Object?, Object?>{
'assets/image.png': <Map<String, Object>>[
<String, Object>{'asset': 'assets/image.png'},
......
......@@ -7,6 +7,7 @@ import 'dart:ui' as ui show Image;
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
class TestImageProvider extends ImageProvider<TestImageProvider> {
const TestImageProvider(this.image);
......@@ -28,10 +29,16 @@ class TestImageProvider extends ImageProvider<TestImageProvider> {
void main() {
late ui.Image testImage;
setUpAll(() async {
testImage = await createTestImage(width: 16, height: 9);
});
testWidgets('DecorationImage RTL with alignment topEnd and match', (WidgetTester tester) async {
tearDownAll(() {
testImage.dispose();
});
testWidgetsWithLeakTracking('DecorationImage RTL with alignment topEnd and match', (WidgetTester tester) async {
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.rtl,
......@@ -70,7 +77,7 @@ void main() {
expect(find.byType(Container), isNot(paints..scale()..scale()));
});
testWidgets('DecorationImage LTR with alignment topEnd (and pointless match)', (WidgetTester tester) async {
testWidgetsWithLeakTracking('DecorationImage LTR with alignment topEnd (and pointless match)', (WidgetTester tester) async {
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
......@@ -106,7 +113,7 @@ void main() {
expect(find.byType(Container), isNot(paints..scale()));
});
testWidgets('DecorationImage RTL with alignment topEnd', (WidgetTester tester) async {
testWidgetsWithLeakTracking('DecorationImage RTL with alignment topEnd', (WidgetTester tester) async {
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.rtl,
......@@ -141,7 +148,7 @@ void main() {
expect(find.byType(Container), isNot(paints..scale()));
});
testWidgets('DecorationImage LTR with alignment topEnd', (WidgetTester tester) async {
testWidgetsWithLeakTracking('DecorationImage LTR with alignment topEnd', (WidgetTester tester) async {
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
......@@ -176,7 +183,7 @@ void main() {
expect(find.byType(Container), isNot(paints..scale()));
});
testWidgets('DecorationImage RTL with alignment center-right and match', (WidgetTester tester) async {
testWidgetsWithLeakTracking('DecorationImage RTL with alignment center-right and match', (WidgetTester tester) async {
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.rtl,
......@@ -208,7 +215,7 @@ void main() {
expect(find.byType(Container), isNot(paints..drawImageRect()..drawImageRect()));
});
testWidgets('DecorationImage RTL with alignment center-right and no match', (WidgetTester tester) async {
testWidgetsWithLeakTracking('DecorationImage RTL with alignment center-right and no match', (WidgetTester tester) async {
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.rtl,
......@@ -235,7 +242,7 @@ void main() {
expect(find.byType(Container), isNot(paints..drawImageRect()..drawImageRect()));
});
testWidgets('DecorationImage LTR with alignment center-right and match', (WidgetTester tester) async {
testWidgetsWithLeakTracking('DecorationImage LTR with alignment center-right and match', (WidgetTester tester) async {
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
......@@ -263,7 +270,7 @@ void main() {
expect(find.byType(Container), isNot(paints..drawImageRect()..drawImageRect()));
});
testWidgets('DecorationImage LTR with alignment center-right and no match', (WidgetTester tester) async {
testWidgetsWithLeakTracking('DecorationImage LTR with alignment center-right and no match', (WidgetTester tester) async {
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
......@@ -291,7 +298,7 @@ void main() {
expect(find.byType(Container), isNot(paints..drawImageRect()..drawImageRect()));
});
testWidgets('Image RTL with alignment topEnd and match', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Image RTL with alignment topEnd and match', (WidgetTester tester) async {
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.rtl,
......@@ -328,7 +335,7 @@ void main() {
expect(find.byType(SizedBox), isNot(paints..scale()..scale()));
});
testWidgets('Image LTR with alignment topEnd (and pointless match)', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Image LTR with alignment topEnd (and pointless match)', (WidgetTester tester) async {
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
......@@ -362,7 +369,7 @@ void main() {
expect(find.byType(SizedBox), isNot(paints..scale()));
});
testWidgets('Image RTL with alignment topEnd', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Image RTL with alignment topEnd', (WidgetTester tester) async {
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.rtl,
......@@ -395,7 +402,7 @@ void main() {
expect(find.byType(SizedBox), isNot(paints..scale()));
});
testWidgets('Image LTR with alignment topEnd', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Image LTR with alignment topEnd', (WidgetTester tester) async {
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
......@@ -428,7 +435,7 @@ void main() {
expect(find.byType(SizedBox), isNot(paints..scale()));
});
testWidgets('Image RTL with alignment center-right and match', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Image RTL with alignment center-right and match', (WidgetTester tester) async {
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.rtl,
......@@ -456,7 +463,7 @@ void main() {
expect(find.byType(SizedBox), isNot(paints..drawImageRect()..drawImageRect()));
});
testWidgets('Image RTL with alignment center-right and no match', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Image RTL with alignment center-right and no match', (WidgetTester tester) async {
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.rtl,
......@@ -481,7 +488,7 @@ void main() {
expect(find.byType(SizedBox), isNot(paints..drawImageRect()..drawImageRect()));
});
testWidgets('Image LTR with alignment center-right and match', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Image LTR with alignment center-right and match', (WidgetTester tester) async {
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
......@@ -507,7 +514,7 @@ void main() {
expect(find.byType(SizedBox), isNot(paints..drawImageRect()..drawImageRect()));
});
testWidgets('Image LTR with alignment center-right and no match', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Image LTR with alignment center-right and no match', (WidgetTester tester) async {
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
......@@ -533,7 +540,7 @@ void main() {
expect(find.byType(SizedBox), isNot(paints..drawImageRect()..drawImageRect()));
});
testWidgets('Image - Switch needing direction', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Image - Switch needing direction', (WidgetTester tester) async {
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
......
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