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'; ...@@ -6,9 +6,10 @@ import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
void main() { void main() {
testWidgets('onSaved callback is called', (WidgetTester tester) async { testWidgetsWithLeakTracking('onSaved callback is called', (WidgetTester tester) async {
final GlobalKey<FormState> formKey = GlobalKey<FormState>(); final GlobalKey<FormState> formKey = GlobalKey<FormState>();
String? fieldValue; String? fieldValue;
...@@ -48,7 +49,7 @@ void main() { ...@@ -48,7 +49,7 @@ void main() {
await checkText(''); await checkText('');
}); });
testWidgets('onChanged callback is called', (WidgetTester tester) async { testWidgetsWithLeakTracking('onChanged callback is called', (WidgetTester tester) async {
String? fieldValue; String? fieldValue;
Widget builder() { Widget builder() {
...@@ -85,7 +86,7 @@ void main() { ...@@ -85,7 +86,7 @@ void main() {
await checkText(''); 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>(); final GlobalKey<FormState> formKey = GlobalKey<FormState>();
String? errorText(String? value) => '${value ?? ''}/error'; String? errorText(String? value) => '${value ?? ''}/error';
...@@ -139,7 +140,7 @@ void main() { ...@@ -139,7 +140,7 @@ void main() {
await checkErrorText(''); 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>(); final GlobalKey<FormState> formKey = GlobalKey<FormState>();
await tester.pumpWidget( await tester.pumpWidget(
MaterialApp( MaterialApp(
...@@ -178,7 +179,7 @@ void main() { ...@@ -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>> fieldKey1 = GlobalKey<FormFieldState<String>>();
final GlobalKey<FormFieldState<String>> fieldKey2 = GlobalKey<FormFieldState<String>>(); final GlobalKey<FormFieldState<String>> fieldKey2 = GlobalKey<FormFieldState<String>>();
const String validString = 'Valid string'; const String validString = 'Valid string';
...@@ -223,7 +224,7 @@ void main() { ...@@ -223,7 +224,7 @@ void main() {
expect(fieldKey2.currentState!.isValid, isTrue); expect(fieldKey2.currentState!.isValid, isTrue);
}); });
testWidgets( testWidgetsWithLeakTracking(
'isValid returns false when the field is invalid and does not change error display', 'isValid returns false when the field is invalid and does not change error display',
(WidgetTester tester) async { (WidgetTester tester) async {
final GlobalKey<FormFieldState<String>> fieldKey1 = GlobalKey<FormFieldState<String>>(); final GlobalKey<FormFieldState<String>> fieldKey1 = GlobalKey<FormFieldState<String>>();
...@@ -272,7 +273,7 @@ void main() { ...@@ -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<FormState> formKey = GlobalKey<FormState>();
final GlobalKey<FormFieldState<String>> fieldKey = GlobalKey<FormFieldState<String>>(); final GlobalKey<FormFieldState<String>> fieldKey = GlobalKey<FormFieldState<String>>();
// Input 2's validator depends on a input 1's value. // Input 2's validator depends on a input 1's value.
...@@ -322,7 +323,7 @@ void main() { ...@@ -322,7 +323,7 @@ void main() {
await checkErrorText(''); 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'; const String initialValue = 'hello';
final GlobalKey<FormFieldState<String>> inputKey = GlobalKey<FormFieldState<String>>(); final GlobalKey<FormFieldState<String>> inputKey = GlobalKey<FormFieldState<String>>();
...@@ -366,8 +367,9 @@ void main() { ...@@ -366,8 +367,9 @@ void main() {
expect(editableText.widget.controller.text, equals('world')); 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'); final TextEditingController controller = TextEditingController(text: 'hello');
addTearDown(controller.dispose);
const String initialValue = 'hello'; const String initialValue = 'hello';
final GlobalKey<FormFieldState<String>> inputKey = GlobalKey<FormFieldState<String>>(); final GlobalKey<FormFieldState<String>> inputKey = GlobalKey<FormFieldState<String>>();
...@@ -413,10 +415,11 @@ void main() { ...@@ -413,10 +415,11 @@ void main() {
expect(controller.text, equals('world')); 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<FormState> formKey = GlobalKey<FormState>();
final GlobalKey<FormFieldState<String>> inputKey = GlobalKey<FormFieldState<String>>(); final GlobalKey<FormFieldState<String>> inputKey = GlobalKey<FormFieldState<String>>();
final TextEditingController controller = TextEditingController(text: 'Plover'); final TextEditingController controller = TextEditingController(text: 'Plover');
addTearDown(controller.dispose);
Widget builder() { Widget builder() {
return MaterialApp( return MaterialApp(
...@@ -459,9 +462,11 @@ void main() { ...@@ -459,9 +462,11 @@ void main() {
expect(controller.text, equals('Plover')); 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'); final TextEditingController controller1 = TextEditingController(text: 'Foo');
addTearDown(controller1.dispose);
final TextEditingController controller2 = TextEditingController(text: 'Bar'); final TextEditingController controller2 = TextEditingController(text: 'Bar');
addTearDown(controller2.dispose);
final GlobalKey<FormFieldState<String>> inputKey = GlobalKey<FormFieldState<String>>(); final GlobalKey<FormFieldState<String>> inputKey = GlobalKey<FormFieldState<String>>();
TextEditingController? currentController; TextEditingController? currentController;
...@@ -566,7 +571,7 @@ void main() { ...@@ -566,7 +571,7 @@ void main() {
expect(controller2.text, equals('Xyzzy')); 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>(); final GlobalKey<FormState> formKey = GlobalKey<FormState>();
String? fieldValue; String? fieldValue;
...@@ -620,7 +625,7 @@ void main() { ...@@ -620,7 +625,7 @@ void main() {
expect(formKey.currentState!.validate(), isTrue); 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; late FormFieldState<String> formFieldState;
String? errorText(String? value) => '$value/error'; String? errorText(String? value) => '$value/error';
...@@ -656,7 +661,7 @@ void main() { ...@@ -656,7 +661,7 @@ void main() {
expect(find.text(errorText('foo')!), findsNothing); 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; late FormFieldState<String> formFieldState;
String? errorText(String? value) => '$value/error'; String? errorText(String? value) => '$value/error';
...@@ -689,7 +694,7 @@ void main() { ...@@ -689,7 +694,7 @@ void main() {
expect(formFieldState.hasError, isTrue); 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'; const String initialValue = 'foo';
String? errorText(String? value) => 'error/$value'; String? errorText(String? value) => 'error/$value';
...@@ -743,7 +748,7 @@ void main() { ...@@ -743,7 +748,7 @@ void main() {
expect(find.text(errorText(initialValue)!), findsNWidgets(2)); 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'; String? errorText(String? value) => 'error/$value';
Widget builder() { Widget builder() {
...@@ -773,7 +778,7 @@ void main() { ...@@ -773,7 +778,7 @@ void main() {
expect(find.text(errorText('')!), findsOneWidget); 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>(); final GlobalKey<FormState> formState = GlobalKey<FormState>();
String? errorText(String? value) => '$value/error'; String? errorText(String? value) => '$value/error';
...@@ -818,7 +823,7 @@ void main() { ...@@ -818,7 +823,7 @@ void main() {
}); });
// Regression test for https://github.com/flutter/flutter/issues/63753. // 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>(); final GlobalKey<FormState> formKey = GlobalKey<FormState>();
String? fieldValue; String? fieldValue;
...@@ -855,7 +860,7 @@ void main() { ...@@ -855,7 +860,7 @@ void main() {
expect(formKey.currentState!.validate(), isFalse); 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 GlobalKey<FormFieldState<String>> fieldKey = GlobalKey<FormFieldState<String>>();
final Widget widget = MaterialApp( final Widget widget = MaterialApp(
...@@ -879,7 +884,7 @@ void main() { ...@@ -879,7 +884,7 @@ void main() {
expect(fieldKey.currentState!.hasInteractedByUser, isFalse); 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 GlobalKey<FormFieldState<String>> fieldKey = GlobalKey<FormFieldState<String>>();
final Widget widget = MaterialApp( final Widget widget = MaterialApp(
...@@ -908,7 +913,7 @@ void main() { ...@@ -908,7 +913,7 @@ void main() {
expect(fieldKey.currentState!.hasInteractedByUser, isTrue); 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 GlobalKey<FormFieldState<String>> fieldKey = GlobalKey<FormFieldState<String>>();
final Widget widget = MaterialApp( final Widget widget = MaterialApp(
......
...@@ -4,9 +4,10 @@ ...@@ -4,9 +4,10 @@
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
void main() { void main() {
testWidgets('FractionallySizedBox', (WidgetTester tester) async { testWidgetsWithLeakTracking('FractionallySizedBox', (WidgetTester tester) async {
final GlobalKey inner = GlobalKey(); final GlobalKey inner = GlobalKey();
await tester.pumpWidget(OverflowBox( await tester.pumpWidget(OverflowBox(
minWidth: 0.0, minWidth: 0.0,
...@@ -29,7 +30,7 @@ void main() { ...@@ -29,7 +30,7 @@ void main() {
expect(box.localToGlobal(Offset.zero), equals(const Offset(25.0, 37.5))); 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(); final GlobalKey inner = GlobalKey();
await tester.pumpWidget(Directionality( await tester.pumpWidget(Directionality(
textDirection: TextDirection.rtl, textDirection: TextDirection.rtl,
...@@ -45,7 +46,7 @@ void main() { ...@@ -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))); 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(); final GlobalKey inner = GlobalKey();
await tester.pumpWidget(Directionality( await tester.pumpWidget(Directionality(
textDirection: TextDirection.rtl, textDirection: TextDirection.rtl,
...@@ -61,7 +62,7 @@ void main() { ...@@ -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))); 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(); final GlobalKey inner = GlobalKey();
await tester.pumpWidget(Directionality( await tester.pumpWidget(Directionality(
textDirection: TextDirection.rtl, textDirection: TextDirection.rtl,
......
...@@ -8,6 +8,7 @@ import 'package:flutter/material.dart'; ...@@ -8,6 +8,7 @@ import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.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); typedef ElementRebuildCallback = void Function(StatefulElement element);
...@@ -22,13 +23,13 @@ class _MyGlobalObjectKey<T extends State<StatefulWidget>> extends GlobalObjectKe ...@@ -22,13 +23,13 @@ class _MyGlobalObjectKey<T extends State<StatefulWidget>> extends GlobalObjectKe
} }
void main() { void main() {
testWidgets('UniqueKey control test', (WidgetTester tester) async { testWidgetsWithLeakTracking('UniqueKey control test', (WidgetTester tester) async {
final Key key = UniqueKey(); final Key key = UniqueKey();
expect(key, hasOneLineDescription); expect(key, hasOneLineDescription);
expect(key, isNot(equals(UniqueKey()))); 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 a = Object();
final Object b = Object(); final Object b = Object();
final Key keyA = ObjectKey(a); final Key keyA = ObjectKey(a);
...@@ -41,7 +42,7 @@ void main() { ...@@ -41,7 +42,7 @@ void main() {
expect(keyA, isNot(equals(keyB))); 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 one = GlobalObjectKey(1);
const GlobalObjectKey<TestState> two = GlobalObjectKey<TestState>(2); const GlobalObjectKey<TestState> two = GlobalObjectKey<TestState>(2);
const GlobalObjectKey three = _MyGlobalObjectKey(3); const GlobalObjectKey three = _MyGlobalObjectKey(3);
...@@ -53,7 +54,7 @@ void main() { ...@@ -53,7 +54,7 @@ void main() {
expect(four.toString(), equals('[_MyGlobalObjectKey<TestState> ${describeIdentity(4)}]')); 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 a = Object();
final Object b = Object(); final Object b = Object();
final Key keyA = GlobalObjectKey(a); final Key keyA = GlobalObjectKey(a);
...@@ -66,7 +67,7 @@ void main() { ...@@ -66,7 +67,7 @@ void main() {
expect(keyA, isNot(equals(keyB))); 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'); final Key key = GlobalKey(debugLabel: 'correct');
await tester.pumpWidget(Stack( await tester.pumpWidget(Stack(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -101,7 +102,7 @@ void main() { ...@@ -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'); final Key key = GlobalKey(debugLabel: 'correct');
await tester.pumpWidget(Stack( await tester.pumpWidget(Stack(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -135,7 +136,7 @@ void main() { ...@@ -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 key1 = GlobalObjectKey('Text1');
const Key key2 = GlobalObjectKey('Text2'); const Key key2 = GlobalObjectKey('Text2');
Key? rebuiltKeyOfSecondChildBeforeLayout; Key? rebuiltKeyOfSecondChildBeforeLayout;
...@@ -224,7 +225,7 @@ void main() { ...@@ -224,7 +225,7 @@ void main() {
expect(rebuiltKeyOfSecondChildAfterLayout, key1); 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 key1 = GlobalObjectKey('Text1');
const Key key2 = GlobalObjectKey('Text2'); const Key key2 = GlobalObjectKey('Text2');
const Key key3 = GlobalObjectKey('Text3'); const Key key3 = GlobalObjectKey('Text3');
...@@ -327,7 +328,7 @@ void main() { ...@@ -327,7 +328,7 @@ void main() {
expect(rebuiltKeyOfThirdChildAfterLayout, key2); 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'); const Key key1 = GlobalObjectKey('Text1');
Key? rebuiltKeyOfSecondChildBeforeLayout; Key? rebuiltKeyOfSecondChildBeforeLayout;
Key? rebuiltKeyOfThirdChildAfterLayout; Key? rebuiltKeyOfThirdChildAfterLayout;
...@@ -418,7 +419,7 @@ void main() { ...@@ -418,7 +419,7 @@ void main() {
expect(rebuiltKeyOfThirdChildAfterLayout, key1); 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'); final Key key = GlobalKey(debugLabel: 'problematic');
await tester.pumpWidget(Stack( await tester.pumpWidget(Stack(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -447,7 +448,7 @@ void main() { ...@@ -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'); final Key key = GlobalKey(debugLabel: 'problematic');
await tester.pumpWidget(Stack( await tester.pumpWidget(Stack(
...@@ -493,7 +494,7 @@ void main() { ...@@ -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'); final Key key = GlobalKey(debugLabel: 'problematic');
await tester.pumpWidget(Stack( await tester.pumpWidget(Stack(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -520,7 +521,7 @@ void main() { ...@@ -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'); final Key key = GlobalKey(debugLabel: 'problematic');
await tester.pumpWidget(Stack( await tester.pumpWidget(Stack(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -547,7 +548,7 @@ void main() { ...@@ -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'); final Key key = GlobalKey(debugLabel: 'problematic');
await tester.pumpWidget(Stack( await tester.pumpWidget(Stack(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -565,7 +566,7 @@ void main() { ...@@ -565,7 +566,7 @@ void main() {
expect(tester.takeException(), isFlutterError); 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'); final Key key = GlobalKey(debugLabel: 'problematic');
await tester.pumpWidget(Stack( await tester.pumpWidget(Stack(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -583,7 +584,7 @@ void main() { ...@@ -583,7 +584,7 @@ void main() {
expect(tester.takeException(), isFlutterError); 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'); final Key key = GlobalKey(debugLabel: 'problematic');
await tester.pumpWidget(Stack( await tester.pumpWidget(Stack(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -602,7 +603,7 @@ void main() { ...@@ -602,7 +603,7 @@ void main() {
expect(tester.takeException(), isFlutterError); 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'); final Key key = GlobalKey(debugLabel: 'problematic');
await tester.pumpWidget(Stack( await tester.pumpWidget(Stack(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -621,7 +622,7 @@ void main() { ...@@ -621,7 +622,7 @@ void main() {
expect(tester.takeException(), isFlutterError); 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'); final Key key = GlobalKey(debugLabel: 'problematic');
await tester.pumpWidget(Stack( await tester.pumpWidget(Stack(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -642,7 +643,7 @@ void main() { ...@@ -642,7 +643,7 @@ void main() {
expect(tester.takeException(), isFlutterError); 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'); final Key key = GlobalKey(debugLabel: 'problematic');
await tester.pumpWidget(Stack( await tester.pumpWidget(Stack(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -663,7 +664,7 @@ void main() { ...@@ -663,7 +664,7 @@ void main() {
expect(tester.takeException(), isFlutterError); 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'); final Key key = GlobalKey(debugLabel: 'problematic');
await tester.pumpWidget(Stack( await tester.pumpWidget(Stack(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -675,7 +676,7 @@ void main() { ...@@ -675,7 +676,7 @@ void main() {
expect(tester.takeException(), isFlutterError); 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 key1 = GlobalKey(debugLabel: 'problematic');
final Key key2 = GlobalKey(debugLabel: 'problematic'); // intentionally the same label final Key key2 = GlobalKey(debugLabel: 'problematic'); // intentionally the same label
final Key key3 = GlobalKey(debugLabel: 'also problematic'); final Key key3 = GlobalKey(debugLabel: 'also problematic');
...@@ -723,7 +724,7 @@ void main() { ...@@ -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 key1 = GlobalKey(debugLabel: 'problematic');
final Key key2 = GlobalKey(debugLabel: 'problematic'); // intentionally the same label final Key key2 = GlobalKey(debugLabel: 'problematic'); // intentionally the same label
final Key key3 = GlobalKey(debugLabel: 'also problematic'); final Key key3 = GlobalKey(debugLabel: 'also problematic');
...@@ -770,7 +771,7 @@ void main() { ...@@ -770,7 +771,7 @@ void main() {
expect(tester.takeException(), isFlutterError); 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'); final Key key = GlobalKey(debugLabel: 'problematic');
await tester.pumpWidget(Stack( await tester.pumpWidget(Stack(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -789,7 +790,7 @@ void main() { ...@@ -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'); final Key key = GlobalKey(debugLabel: 'problematic');
await tester.pumpWidget(Stack( await tester.pumpWidget(Stack(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -810,7 +811,7 @@ void main() { ...@@ -810,7 +811,7 @@ void main() {
expect(tester.takeException(), isFlutterError); 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'); final Key key = GlobalKey(debugLabel: 'problematic');
await tester.pumpWidget(Stack( await tester.pumpWidget(Stack(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -829,7 +830,7 @@ void main() { ...@@ -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'); final Key key = GlobalKey(debugLabel: 'problematic');
await tester.pumpWidget(Stack( await tester.pumpWidget(Stack(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -857,7 +858,7 @@ void main() { ...@@ -857,7 +858,7 @@ void main() {
expect(count, 1); 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 Key key = GlobalKey(debugLabel: 'problematic');
final Stack stack = Stack( final Stack stack = Stack(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -894,7 +895,7 @@ void main() { ...@@ -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 Key key = GlobalKey(debugLabel: 'problematic');
final Stack stack = Stack( final Stack stack = Stack(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -922,7 +923,7 @@ void main() { ...@@ -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 key1 = GlobalObjectKey('Text1');
const Key key2 = GlobalObjectKey('Text2'); const Key key2 = GlobalObjectKey('Text2');
Key? rebuiltKeyOfSecondChildBeforeLayout; Key? rebuiltKeyOfSecondChildBeforeLayout;
...@@ -1023,14 +1024,17 @@ void main() { ...@@ -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( await tester.pumpWidget(Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
child: Center( child: Center(
child: SizedBox( child: SizedBox(
height: 100, height: 100,
child: CustomScrollView( child: CustomScrollView(
controller: ScrollController(), controller: scrollController,
slivers: <Widget>[ slivers: <Widget>[
SliverList( SliverList(
delegate: SliverChildListDelegate(<Widget>[ delegate: SliverChildListDelegate(<Widget>[
...@@ -1058,7 +1062,7 @@ void main() { ...@@ -1058,7 +1062,7 @@ void main() {
element.createChild(0, after: null); 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 // This is a regression test for https://github.com/flutter/flutter/issues/62055
const Key key1 = GlobalObjectKey('key1'); const Key key1 = GlobalObjectKey('key1');
const Key key2 = GlobalObjectKey('key2'); const Key key2 = GlobalObjectKey('key2');
...@@ -1104,7 +1108,7 @@ void main() { ...@@ -1104,7 +1108,7 @@ void main() {
expect(tabController.index, 0); expect(tabController.index, 0);
}); });
testWidgets('Defunct setState throws exception', (WidgetTester tester) async { testWidgetsWithLeakTracking('Defunct setState throws exception', (WidgetTester tester) async {
late StateSetter setState; late StateSetter setState;
await tester.pumpWidget(StatefulBuilder( await tester.pumpWidget(StatefulBuilder(
...@@ -1122,12 +1126,12 @@ void main() { ...@@ -1122,12 +1126,12 @@ void main() {
expect(() { setState(() { }); }, throwsFlutterError); expect(() { setState(() { }); }, throwsFlutterError);
}); });
testWidgets('State toString', (WidgetTester tester) async { testWidgetsWithLeakTracking('State toString', (WidgetTester tester) async {
final TestState state = TestState(); final TestState state = TestState();
expect(state.toString(), contains('no widget')); expect(state.toString(), contains('no widget'));
}); });
testWidgets('debugPrintGlobalKeyedWidgetLifecycle control test', (WidgetTester tester) async { testWidgetsWithLeakTracking('debugPrintGlobalKeyedWidgetLifecycle control test', (WidgetTester tester) async {
expect(debugPrintGlobalKeyedWidgetLifecycle, isFalse); expect(debugPrintGlobalKeyedWidgetLifecycle, isFalse);
final DebugPrintCallback oldCallback = debugPrint; final DebugPrintCallback oldCallback = debugPrint;
...@@ -1150,7 +1154,7 @@ void main() { ...@@ -1150,7 +1154,7 @@ void main() {
expect(log[1], matches('Discarding .+ from inactive elements list.')); 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; GlobalKey key0, key1, key2;
await tester.pumpWidget(Column( await tester.pumpWidget(Column(
key: key0 = GlobalKey(), key: key0 = GlobalKey(),
...@@ -1169,7 +1173,7 @@ void main() { ...@@ -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( await tester.pumpWidget(
Column( Column(
children: <Widget>[ children: <Widget>[
...@@ -1194,7 +1198,7 @@ void main() { ...@@ -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( await tester.pumpWidget(
Column( Column(
children: <Widget>[ children: <Widget>[
...@@ -1227,7 +1231,7 @@ void main() { ...@@ -1227,7 +1231,7 @@ void main() {
); );
}); });
testWidgets('Element diagnostics', (WidgetTester tester) async { testWidgetsWithLeakTracking('Element diagnostics', (WidgetTester tester) async {
GlobalKey key0; GlobalKey key0;
await tester.pumpWidget(Column( await tester.pumpWidget(Column(
key: key0 = GlobalKey(), key: key0 = GlobalKey(),
...@@ -1319,7 +1323,7 @@ void main() { ...@@ -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>(); final GlobalKey<DependentState> key = GlobalKey<DependentState>();
/// Initial build - should call didChangeDependencies, not deactivate /// Initial build - should call didChangeDependencies, not deactivate
...@@ -1348,7 +1352,7 @@ void main() { ...@@ -1348,7 +1352,7 @@ void main() {
expect(state.deactivatedCount, 2); 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 isDidChangeDependenciesDecorated;
late bool isBuildDecorated; late bool isBuildDecorated;
...@@ -1372,7 +1376,7 @@ void main() { ...@@ -1372,7 +1376,7 @@ void main() {
expect(isDidChangeDependenciesDecorated, isFalse); expect(isDidChangeDependenciesDecorated, isFalse);
}); });
group('BuildContext.debugDoingbuild', () { group('BuildContext.debugDoingbuild', () {
testWidgets('StatelessWidget', (WidgetTester tester) async { testWidgetsWithLeakTracking('StatelessWidget', (WidgetTester tester) async {
late bool debugDoingBuildOnBuild; late bool debugDoingBuildOnBuild;
await tester.pumpWidget( await tester.pumpWidget(
StatelessWidgetSpy( StatelessWidgetSpy(
...@@ -1387,7 +1391,7 @@ void main() { ...@@ -1387,7 +1391,7 @@ void main() {
expect(context.debugDoingBuild, isFalse); expect(context.debugDoingBuild, isFalse);
expect(debugDoingBuildOnBuild, isTrue); expect(debugDoingBuildOnBuild, isTrue);
}); });
testWidgets('StatefulWidget', (WidgetTester tester) async { testWidgetsWithLeakTracking('StatefulWidget', (WidgetTester tester) async {
late bool debugDoingBuildOnBuild; late bool debugDoingBuildOnBuild;
late bool debugDoingBuildOnInitState; late bool debugDoingBuildOnInitState;
late bool debugDoingBuildOnDidChangeDependencies; late bool debugDoingBuildOnDidChangeDependencies;
...@@ -1456,11 +1460,12 @@ void main() { ...@@ -1456,11 +1460,12 @@ void main() {
expect(debugDoingBuildOnDispose, isFalse); expect(debugDoingBuildOnDispose, isFalse);
expect(debugDoingBuildOnDeactivate, isFalse); expect(debugDoingBuildOnDeactivate, isFalse);
}); });
testWidgets('RenderObjectWidget', (WidgetTester tester) async { testWidgetsWithLeakTracking('RenderObjectWidget', (WidgetTester tester) async {
late bool debugDoingBuildOnCreateRenderObject; late bool debugDoingBuildOnCreateRenderObject;
bool? debugDoingBuildOnUpdateRenderObject; bool? debugDoingBuildOnUpdateRenderObject;
bool? debugDoingBuildOnDidUnmountRenderObject; bool? debugDoingBuildOnDidUnmountRenderObject;
final ValueNotifier<int> notifier = ValueNotifier<int>(0); final ValueNotifier<int> notifier = ValueNotifier<int>(0);
addTearDown(notifier.dispose);
late BuildContext spyContext; late BuildContext spyContext;
...@@ -1516,7 +1521,7 @@ void main() { ...@@ -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(); final GlobalKey key = GlobalKey();
await tester.pumpWidget(_WidgetWithNoVisitChildren(_StatefulLeaf(key: key))); await tester.pumpWidget(_WidgetWithNoVisitChildren(_StatefulLeaf(key: key)));
(key.currentState! as _StatefulLeafState).markNeedsBuild(); (key.currentState! as _StatefulLeafState).markNeedsBuild();
...@@ -1542,11 +1547,13 @@ void main() { ...@@ -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 int pointerRouterCount = GestureBinding.instance.pointerRouter.debugGlobalRouteCount;
final RawKeyEventHandler? rawKeyEventHandler = RawKeyboard.instance.keyEventHandler; final RawKeyEventHandler? rawKeyEventHandler = RawKeyboard.instance.keyEventHandler;
expect(rawKeyEventHandler, isNotNull); expect(rawKeyEventHandler, isNotNull);
BuildOwner(focusManager: FocusManager()); final FocusManager focusManager = FocusManager();
addTearDown(focusManager.dispose);
BuildOwner(focusManager: focusManager);
expect(GestureBinding.instance.pointerRouter.debugGlobalRouteCount, pointerRouterCount); expect(GestureBinding.instance.pointerRouter.debugGlobalRouteCount, pointerRouterCount);
expect(RawKeyboard.instance.keyEventHandler, same(rawKeyEventHandler)); expect(RawKeyboard.instance.keyEventHandler, same(rawKeyEventHandler));
}); });
...@@ -1601,7 +1608,7 @@ void main() { ...@@ -1601,7 +1608,7 @@ void main() {
expect(dependenciesProperty.toDescription(), '[ButtonBarTheme, Directionality, FocusTraversalOrder]'); 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 int initialCount = tester.binding.buildOwner!.globalKeyCount;
final GlobalKey key1 = GlobalKey(); final GlobalKey key1 = GlobalKey();
final GlobalKey key2 = GlobalKey(); final GlobalKey key2 = GlobalKey();
...@@ -1615,7 +1622,7 @@ void main() { ...@@ -1615,7 +1622,7 @@ void main() {
expect(tester.binding.buildOwner!.globalKeyCount, initialCount + 0); 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()); await tester.pumpWidget(const _StatefulLeaf());
final StatefulElement element = tester.element<StatefulElement>(find.byType(_StatefulLeaf)); final StatefulElement element = tester.element<StatefulElement>(find.byType(_StatefulLeaf));
expect(element.state, isA<State<_StatefulLeaf>>()); expect(element.state, isA<State<_StatefulLeaf>>());
...@@ -1631,7 +1638,7 @@ void main() { ...@@ -1631,7 +1638,7 @@ void main() {
expect(() => element.widget, throwsA(isA<TypeError>())); 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. // Regression test for https://github.com/flutter/flutter/issues/96959.
final LayerLink link = LayerLink(); final LayerLink link = LayerLink();
await tester.pumpWidget(_TestLeaderLayerWidget( await tester.pumpWidget(_TestLeaderLayerWidget(
...@@ -1653,7 +1660,7 @@ void main() { ...@@ -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>[]; final List<String> states = <String>[];
Widget build([Key? key]) { Widget build([Key? key]) {
return StatefulWidgetSpy( return StatefulWidgetSpy(
...@@ -1687,7 +1694,7 @@ void main() { ...@@ -1687,7 +1694,7 @@ void main() {
expect(states, <String>['deactivate', 'dispose']); 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()); await tester.pumpWidget(const Placeholder());
final RenderObjectElement element = tester.allElements.whereType<RenderObjectElement>().last; final RenderObjectElement element = tester.allElements.whereType<RenderObjectElement>().last;
final RenderObject renderObject = element.renderObject; final RenderObject renderObject = element.renderObject;
...@@ -1699,7 +1706,7 @@ void main() { ...@@ -1699,7 +1706,7 @@ void main() {
expect(renderObject.debugDisposed, true); 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()); await tester.pumpWidget(const _StatefulLeaf());
final StatefulElement element = tester.element<StatefulElement>(find.byType(_StatefulLeaf)); final StatefulElement element = tester.element<StatefulElement>(find.byType(_StatefulLeaf));
expect(element.state, isA<State<_StatefulLeaf>>()); expect(element.state, isA<State<_StatefulLeaf>>());
...@@ -1754,7 +1761,7 @@ The findRenderObject() method was called for the following element: ...@@ -1754,7 +1761,7 @@ The findRenderObject() method was called for the following element:
expect(child.doesDependOnInheritedElement(ancestor), isTrue); expect(child.doesDependOnInheritedElement(ancestor), isTrue);
}); });
testWidgets( testWidgetsWithLeakTracking(
'MultiChildRenderObjectElement.updateChildren test', 'MultiChildRenderObjectElement.updateChildren test',
(WidgetTester tester) async { (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/120762. // Regression test for https://github.com/flutter/flutter/issues/120762.
......
...@@ -6,11 +6,12 @@ import 'package:flutter/gestures.dart'; ...@@ -6,11 +6,12 @@ import 'package:flutter/gestures.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
import 'semantics_tester.dart'; import 'semantics_tester.dart';
void main() { 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); final SemanticsTester semantics = SemanticsTester(tester);
int callCount = 0; int callCount = 0;
...@@ -44,7 +45,7 @@ void main() { ...@@ -44,7 +45,7 @@ void main() {
semantics.dispose(); 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); final SemanticsTester semantics = SemanticsTester(tester);
int callCount = 0; int callCount = 0;
...@@ -78,7 +79,7 @@ void main() { ...@@ -78,7 +79,7 @@ void main() {
semantics.dispose(); 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 SemanticsTester semantics = SemanticsTester(tester);
final Set<String> logs = <String>{}; final Set<String> logs = <String>{};
...@@ -102,7 +103,7 @@ void main() { ...@@ -102,7 +103,7 @@ void main() {
semantics.dispose(); 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); final SemanticsTester semantics = SemanticsTester(tester);
// How the test is set up: // How the test is set up:
...@@ -173,7 +174,7 @@ void main() { ...@@ -173,7 +174,7 @@ void main() {
}); });
group("RawGestureDetector's custom semantics delegate", () { 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 SemanticsTester semantics = SemanticsTester(tester);
final Map<Type, GestureRecognizerFactory> gestures = final Map<Type, GestureRecognizerFactory> gestures =
_buildGestureMap(() => LongPressGestureRecognizer(), null) _buildGestureMap(() => LongPressGestureRecognizer(), null)
...@@ -208,7 +209,7 @@ void main() { ...@@ -208,7 +209,7 @@ void main() {
semantics.dispose(); 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 SemanticsTester semantics = SemanticsTester(tester);
final Map<Type, GestureRecognizerFactory> gestures = final Map<Type, GestureRecognizerFactory> gestures =
_buildGestureMap(() => LongPressGestureRecognizer(), null) _buildGestureMap(() => LongPressGestureRecognizer(), null)
...@@ -243,7 +244,7 @@ void main() { ...@@ -243,7 +244,7 @@ void main() {
semantics.dispose(); 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 SemanticsTester semantics = SemanticsTester(tester);
final Map<Type, GestureRecognizerFactory> gestures = final Map<Type, GestureRecognizerFactory> gestures =
_buildGestureMap(() => LongPressGestureRecognizer(), null) _buildGestureMap(() => LongPressGestureRecognizer(), null)
...@@ -279,7 +280,7 @@ void main() { ...@@ -279,7 +280,7 @@ void main() {
semantics.dispose(); semantics.dispose();
}); });
testWidgets('should correctly call callbacks', (WidgetTester tester) async { testWidgetsWithLeakTracking('should correctly call callbacks', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester); final SemanticsTester semantics = SemanticsTester(tester);
final List<String> logs = <String>[]; final List<String> logs = <String>[];
final GlobalKey<RawGestureDetectorState> detectorKey = GlobalKey(); final GlobalKey<RawGestureDetectorState> detectorKey = GlobalKey();
...@@ -321,7 +322,7 @@ void main() { ...@@ -321,7 +322,7 @@ void main() {
group("RawGestureDetector's default semantics delegate", () { group("RawGestureDetector's default semantics delegate", () {
group('should map onTap to', () { 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); final SemanticsTester semantics = SemanticsTester(tester);
await tester.pumpWidget( await tester.pumpWidget(
Center( Center(
...@@ -339,7 +340,7 @@ void main() { ...@@ -339,7 +340,7 @@ void main() {
semantics.dispose(); 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); final SemanticsTester semantics = SemanticsTester(tester);
await tester.pumpWidget( await tester.pumpWidget(
Center( Center(
...@@ -360,7 +361,7 @@ void main() { ...@@ -360,7 +361,7 @@ void main() {
semantics.dispose(); 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 SemanticsTester semantics = SemanticsTester(tester);
final GlobalKey detectorKey = GlobalKey(); final GlobalKey detectorKey = GlobalKey();
final List<String> logs = <String>[]; final List<String> logs = <String>[];
...@@ -394,7 +395,7 @@ void main() { ...@@ -394,7 +395,7 @@ void main() {
}); });
group('should map onLongPress to', () { 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); final SemanticsTester semantics = SemanticsTester(tester);
await tester.pumpWidget( await tester.pumpWidget(
Center( Center(
...@@ -412,7 +413,7 @@ void main() { ...@@ -412,7 +413,7 @@ void main() {
semantics.dispose(); 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); final SemanticsTester semantics = SemanticsTester(tester);
await tester.pumpWidget( await tester.pumpWidget(
Center( Center(
...@@ -433,7 +434,7 @@ void main() { ...@@ -433,7 +434,7 @@ void main() {
semantics.dispose(); 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 SemanticsTester semantics = SemanticsTester(tester);
final GlobalKey detectorKey = GlobalKey(); final GlobalKey detectorKey = GlobalKey();
final List<String> logs = <String>[]; final List<String> logs = <String>[];
...@@ -466,7 +467,7 @@ void main() { ...@@ -466,7 +467,7 @@ void main() {
}); });
group('should map onHorizontalDragUpdate to', () { 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); final SemanticsTester semantics = SemanticsTester(tester);
await tester.pumpWidget( await tester.pumpWidget(
Center( Center(
...@@ -484,7 +485,7 @@ void main() { ...@@ -484,7 +485,7 @@ void main() {
semantics.dispose(); 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); final SemanticsTester semantics = SemanticsTester(tester);
await tester.pumpWidget( await tester.pumpWidget(
Center( Center(
...@@ -526,7 +527,7 @@ void main() { ...@@ -526,7 +527,7 @@ void main() {
semantics.dispose(); 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 SemanticsTester semantics = SemanticsTester(tester);
final GlobalKey detectorKey = GlobalKey(); final GlobalKey detectorKey = GlobalKey();
final List<String> logs = <String>[]; final List<String> logs = <String>[];
...@@ -576,7 +577,7 @@ void main() { ...@@ -576,7 +577,7 @@ void main() {
}); });
group('should map onVerticalDragUpdate to', () { 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); final SemanticsTester semantics = SemanticsTester(tester);
await tester.pumpWidget( await tester.pumpWidget(
Center( Center(
...@@ -594,7 +595,7 @@ void main() { ...@@ -594,7 +595,7 @@ void main() {
semantics.dispose(); 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); final SemanticsTester semantics = SemanticsTester(tester);
await tester.pumpWidget( await tester.pumpWidget(
Center( Center(
...@@ -617,7 +618,7 @@ void main() { ...@@ -617,7 +618,7 @@ void main() {
semantics.dispose(); 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 SemanticsTester semantics = SemanticsTester(tester);
final GlobalKey detectorKey = GlobalKey(); final GlobalKey detectorKey = GlobalKey();
final List<String> logs = <String>[]; final List<String> logs = <String>[];
...@@ -666,7 +667,7 @@ void main() { ...@@ -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); final SemanticsTester semantics = SemanticsTester(tester);
await tester.pumpWidget( await tester.pumpWidget(
Center( Center(
......
...@@ -6,11 +6,12 @@ import 'package:flutter/gestures.dart'; ...@@ -6,11 +6,12 @@ import 'package:flutter/gestures.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
void main() { void main() {
const Offset forcePressOffset = Offset(400.0, 50.0); 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; bool didStartDrag = false;
double? updatedDragDelta; double? updatedDragDelta;
bool didEndDrag = false; bool didEndDrag = false;
...@@ -58,7 +59,7 @@ void main() { ...@@ -58,7 +59,7 @@ void main() {
await tester.pumpWidget(Container()); 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; int gestureCount = 0;
double dragDistance = 0.0; double dragDistance = 0.0;
...@@ -91,7 +92,7 @@ void main() { ...@@ -91,7 +92,7 @@ void main() {
await tester.pumpWidget(Container()); await tester.pumpWidget(Container());
}); });
testWidgets("Pan doesn't crash", (WidgetTester tester) async { testWidgetsWithLeakTracking("Pan doesn't crash", (WidgetTester tester) async {
bool didStartPan = false; bool didStartPan = false;
Offset? panDelta; Offset? panDelta;
bool didEndPan = false; bool didEndPan = false;
...@@ -135,7 +136,7 @@ void main() { ...@@ -135,7 +136,7 @@ void main() {
}, },
); );
testWidgets('Translucent', (WidgetTester tester) async { testWidgetsWithLeakTracking('Translucent', (WidgetTester tester) async {
bool didReceivePointerDown; bool didReceivePointerDown;
bool didTap; bool didTap;
...@@ -206,7 +207,7 @@ void main() { ...@@ -206,7 +207,7 @@ void main() {
expect(didTap, isTrue); expect(didTap, isTrue);
}, variant: buttonVariant); }, variant: buttonVariant);
testWidgets('Empty', (WidgetTester tester) async { testWidgetsWithLeakTracking('Empty', (WidgetTester tester) async {
bool didTap = false; bool didTap = false;
await tester.pumpWidget( await tester.pumpWidget(
Center( Center(
...@@ -228,7 +229,7 @@ void main() { ...@@ -228,7 +229,7 @@ void main() {
expect(didTap, isTrue); expect(didTap, isTrue);
}, variant: buttonVariant); }, variant: buttonVariant);
testWidgets('Only container', (WidgetTester tester) async { testWidgetsWithLeakTracking('Only container', (WidgetTester tester) async {
bool didTap = false; bool didTap = false;
await tester.pumpWidget( await tester.pumpWidget(
Center( Center(
...@@ -251,7 +252,7 @@ void main() { ...@@ -251,7 +252,7 @@ void main() {
expect(didTap, isFalse); expect(didTap, isFalse);
}, variant: buttonVariant); }, variant: buttonVariant);
testWidgets('cache render object', (WidgetTester tester) async { testWidgetsWithLeakTracking('cache render object', (WidgetTester tester) async {
void inputCallback() { } void inputCallback() { }
await tester.pumpWidget( await tester.pumpWidget(
...@@ -283,7 +284,7 @@ void main() { ...@@ -283,7 +284,7 @@ void main() {
expect(renderObj1, same(renderObj2)); expect(renderObj1, same(renderObj2));
}, variant: buttonVariant); }, variant: buttonVariant);
testWidgets('Tap down occurs after kPressTimeout', (WidgetTester tester) async { testWidgetsWithLeakTracking('Tap down occurs after kPressTimeout', (WidgetTester tester) async {
int tapDown = 0; int tapDown = 0;
int tap = 0; int tap = 0;
int tapCancel = 0; int tapCancel = 0;
...@@ -391,7 +392,7 @@ void main() { ...@@ -391,7 +392,7 @@ void main() {
expect(longPress, 1); expect(longPress, 1);
}, variant: buttonVariant); }, 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; int longPressUp = 0;
await tester.pumpWidget( await tester.pumpWidget(
...@@ -441,7 +442,7 @@ void main() { ...@@ -441,7 +442,7 @@ void main() {
}, variant: buttonVariant); }, 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; bool primaryLongPress = false, secondaryLongPress = false;
await tester.pumpWidget( await tester.pumpWidget(
...@@ -477,7 +478,7 @@ void main() { ...@@ -477,7 +478,7 @@ void main() {
expect(secondaryLongPress, isTrue); 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 forcePressStart = 0;
int forcePressPeaked = 0; int forcePressPeaked = 0;
int forcePressUpdate = 0; int forcePressUpdate = 0;
...@@ -580,7 +581,7 @@ void main() { ...@@ -580,7 +581,7 @@ void main() {
expect(forcePressEnded, 1); 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 forcePressStart = 0;
int longPressTimes = 0; int longPressTimes = 0;
...@@ -645,7 +646,7 @@ void main() { ...@@ -645,7 +646,7 @@ void main() {
expect(forcePressStart, 0); 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 forcePressStart = 0;
int horizontalDragStart = 0; int horizontalDragStart = 0;
...@@ -706,7 +707,7 @@ void main() { ...@@ -706,7 +707,7 @@ void main() {
}); });
group("RawGestureDetectorState's debugFillProperties", () { group("RawGestureDetectorState's debugFillProperties", () {
testWidgets('when default', (WidgetTester tester) async { testWidgetsWithLeakTracking('when default', (WidgetTester tester) async {
final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder(); final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder();
final GlobalKey key = GlobalKey(); final GlobalKey key = GlobalKey();
await tester.pumpWidget(RawGestureDetector( await tester.pumpWidget(RawGestureDetector(
...@@ -724,7 +725,7 @@ void main() { ...@@ -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 DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder();
final GlobalKey key = GlobalKey(); final GlobalKey key = GlobalKey();
await tester.pumpWidget(RawGestureDetector( await tester.pumpWidget(RawGestureDetector(
...@@ -761,7 +762,7 @@ void main() { ...@@ -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 DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder();
final GlobalKey key = GlobalKey(); final GlobalKey key = GlobalKey();
await tester.pumpWidget(RawGestureDetector( await tester.pumpWidget(RawGestureDetector(
...@@ -832,7 +833,7 @@ void main() { ...@@ -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>(); final GlobalKey<RawGestureDetectorState> key = GlobalKey<RawGestureDetectorState>();
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
...@@ -876,7 +877,7 @@ void main() { ...@@ -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 // Regression test for https://github.com/flutter/flutter/issues/111716
bool didStartPan = false; bool didStartPan = false;
Offset? panDelta; Offset? panDelta;
...@@ -946,7 +947,7 @@ void main() { ...@@ -946,7 +947,7 @@ void main() {
expect(didEndPan, isTrue); expect(didEndPan, isTrue);
}); });
testWidgets('supportedDevices is respected', (WidgetTester tester) async { testWidgetsWithLeakTracking('supportedDevices is respected', (WidgetTester tester) async {
bool didStartPan = false; bool didStartPan = false;
Offset? panDelta; Offset? panDelta;
bool didEndPan = false; bool didEndPan = false;
...@@ -994,7 +995,7 @@ void main() { ...@@ -994,7 +995,7 @@ void main() {
}); });
group('DoubleTap', () { 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>[]; final List<String> log = <String>[];
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
...@@ -1017,7 +1018,7 @@ void main() { ...@@ -1017,7 +1018,7 @@ void main() {
expect(log, <String>['double-tap']); 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>[]; final List<String> log = <String>[];
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
......
...@@ -4,9 +4,10 @@ ...@@ -4,9 +4,10 @@
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
void main() { 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 detector1TapCount = 0;
int detector2TapCount = 0; int detector2TapCount = 0;
......
...@@ -5,11 +5,12 @@ ...@@ -5,11 +5,12 @@
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.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. // There's also some duplicate GlobalKey tests in the framework_test.dart file.
void main() { 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 // This is actually a test of the regular duplicate key logic, which
// happens before the duplicate GlobalKey logic. // happens before the duplicate GlobalKey logic.
await tester.pumpWidget(const Stack(children: <Widget>[ await tester.pumpWidget(const Stack(children: <Widget>[
...@@ -23,7 +24,7 @@ void main() { ...@@ -23,7 +24,7 @@ void main() {
expect(error.toString(), contains('[GlobalObjectKey ${describeIdentity(0)}]')); 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( await tester.pumpWidget(const Stack(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
children: <Widget>[ children: <Widget>[
...@@ -43,7 +44,7 @@ void main() { ...@@ -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.')); 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( await tester.pumpWidget(const Stack(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
children: <Widget>[ children: <Widget>[
...@@ -61,7 +62,7 @@ void main() { ...@@ -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.')); 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; late StateSetter nestedSetState;
bool flag = false; bool flag = false;
await tester.pumpWidget(Stack( await tester.pumpWidget(Stack(
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
class Item { class Item {
GlobalKey key1 = GlobalKey(); GlobalKey key1 = GlobalKey();
...@@ -55,7 +56,7 @@ Widget builder() { ...@@ -55,7 +56,7 @@ Widget builder() {
} }
void main() { 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()); await tester.pumpWidget(builder());
final StatefulLeafState leaf = tester.firstState(find.byType(StatefulLeaf)); final StatefulLeafState leaf = tester.firstState(find.byType(StatefulLeaf));
leaf.markNeedsBuild(); leaf.markNeedsBuild();
......
...@@ -5,9 +5,10 @@ ...@@ -5,9 +5,10 @@
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
void main() { void main() {
testWidgets('GridPaper control test', (WidgetTester tester) async { testWidgetsWithLeakTracking('GridPaper control test', (WidgetTester tester) async {
await tester.pumpWidget(const GridPaper()); await tester.pumpWidget(const GridPaper());
final List<Layer> layers1 = tester.layers; final List<Layer> layers1 = tester.layers;
await tester.pumpWidget(const GridPaper()); await tester.pumpWidget(const GridPaper());
......
...@@ -4,9 +4,10 @@ ...@@ -4,9 +4,10 @@
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
void main() { void main() {
testWidgets('Empty GridView', (WidgetTester tester) async { testWidgetsWithLeakTracking('Empty GridView', (WidgetTester tester) async {
final List<Widget> children = <Widget>[ final List<Widget> children = <Widget>[
const DecoratedBox(decoration: BoxDecoration()), const DecoratedBox(decoration: BoxDecoration()),
const DecoratedBox(decoration: BoxDecoration()), const DecoratedBox(decoration: BoxDecoration()),
......
...@@ -6,13 +6,14 @@ import 'package:flutter/gestures.dart' show DragStartBehavior; ...@@ -6,13 +6,14 @@ import 'package:flutter/gestures.dart' show DragStartBehavior;
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.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 '../rendering/rendering_tester.dart' show TestClipPaintingContext;
import 'states.dart'; import 'states.dart';
void main() { void main() {
// Regression test for https://github.com/flutter/flutter/issues/100451 // 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; bool finderCalled = false;
int itemCount = 7; int itemCount = 7;
late StateSetter stateSetter; late StateSetter stateSetter;
...@@ -50,7 +51,7 @@ void main() { ...@@ -50,7 +51,7 @@ void main() {
expect(finderCalled, true); expect(finderCalled, true);
}); });
testWidgets('Empty GridView', (WidgetTester tester) async { testWidgetsWithLeakTracking('Empty GridView', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -62,7 +63,7 @@ void main() { ...@@ -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>[]; final List<String> log = <String>[];
await tester.pumpWidget( await tester.pumpWidget(
...@@ -135,7 +136,7 @@ void main() { ...@@ -135,7 +136,7 @@ void main() {
log.clear(); log.clear();
}); });
testWidgets('GridView.extent control test', (WidgetTester tester) async { testWidgetsWithLeakTracking('GridView.extent control test', (WidgetTester tester) async {
final List<String> log = <String>[]; final List<String> log = <String>[];
await tester.pumpWidget( await tester.pumpWidget(
...@@ -182,7 +183,7 @@ void main() { ...@@ -182,7 +183,7 @@ void main() {
log.clear(); log.clear();
}); });
testWidgets('GridView large scroll jump', (WidgetTester tester) async { testWidgetsWithLeakTracking('GridView large scroll jump', (WidgetTester tester) async {
final List<int> log = <int>[]; final List<int> log = <int>[];
await tester.pumpWidget( await tester.pumpWidget(
...@@ -274,7 +275,7 @@ void main() { ...@@ -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>[]; final List<int> log = <int>[];
await tester.pumpWidget( await tester.pumpWidget(
...@@ -345,7 +346,7 @@ void main() { ...@@ -345,7 +346,7 @@ void main() {
expect(find.text('4'), findsNothing); 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( const SliverGridDelegateWithMaxCrossAxisExtent delegate = SliverGridDelegateWithMaxCrossAxisExtent(
childAspectRatio: 1e300, childAspectRatio: 1e300,
maxCrossAxisExtent: 500.0, maxCrossAxisExtent: 500.0,
...@@ -369,7 +370,7 @@ void main() { ...@@ -369,7 +370,7 @@ void main() {
expect(layout.getMinChildIndexForScrollOffset(1000.0), 0.0); 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>[]; final List<int> log = <int>[];
await tester.pumpWidget( await tester.pumpWidget(
...@@ -440,7 +441,7 @@ void main() { ...@@ -440,7 +441,7 @@ void main() {
expect(find.text('4'), findsNothing); 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); const Color green = Color(0xFF00FF00);
final Container container = Container( final Container container = Container(
...@@ -469,7 +470,7 @@ void main() { ...@@ -469,7 +470,7 @@ void main() {
expect(find.byType(GridView), isNot(paints..rect(color: green)..rect(color: green)..rect(color: green))); 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( await tester.pumpWidget(
Directionality( Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -490,7 +491,7 @@ void main() { ...@@ -490,7 +491,7 @@ void main() {
expect(find.text('1'), findsNothing); expect(find.text('1'), findsNothing);
}); });
testWidgets('GridView in unbounded context', (WidgetTester tester) async { testWidgetsWithLeakTracking('GridView in unbounded context', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -510,7 +511,7 @@ void main() { ...@@ -510,7 +511,7 @@ void main() {
expect(find.text('19'), findsOneWidget); expect(find.text('19'), findsOneWidget);
}); });
testWidgets('GridView.builder control test', (WidgetTester tester) async { testWidgetsWithLeakTracking('GridView.builder control test', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -531,7 +532,7 @@ void main() { ...@@ -531,7 +532,7 @@ void main() {
expect(find.text('12'), findsNothing); 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( await tester.pumpWidget(
Directionality( Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -553,7 +554,7 @@ void main() { ...@@ -553,7 +554,7 @@ void main() {
expect(find.text('13'), findsOneWidget); 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(); final Key target = UniqueKey();
Widget build(TextDirection textDirection) { Widget build(TextDirection textDirection) {
...@@ -579,7 +580,7 @@ void main() { ...@@ -579,7 +580,7 @@ void main() {
expect(tester.getBottomRight(find.byKey(target)), const Offset(800.0, 200.0)); 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. // Regression test for https://github.com/flutter/flutter/issues/27151.
final Key target = UniqueKey(); final Key target = UniqueKey();
...@@ -607,7 +608,7 @@ void main() { ...@@ -607,7 +608,7 @@ void main() {
expect(tester.getBottomRight(find.byKey(target)), const Offset(800.0, 194.0)); 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>{}; final Map<int, int> counters = <int, int>{};
await tester.pumpWidget(Directionality( await tester.pumpWidget(Directionality(
...@@ -642,7 +643,7 @@ void main() { ...@@ -642,7 +643,7 @@ void main() {
expect(counters[4], 2); 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( await tester.pumpWidget(
Directionality( Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -663,9 +664,18 @@ void main() { ...@@ -663,9 +664,18 @@ void main() {
final TestClipPaintingContext context = TestClipPaintingContext(); final TestClipPaintingContext context = TestClipPaintingContext();
renderObject.paint(context, Offset.zero); renderObject.paint(context, Offset.zero);
expect(context.clipBehavior, equals(Clip.none)); expect(context.clipBehavior, equals(Clip.none));
}); },
leakTrackingTestConfig: const LeakTrackingTestConfig(
testWidgets('GridView respects clipBehavior', (WidgetTester tester) async { // 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,
},
));
testWidgetsWithLeakTracking('GridView respects clipBehavior', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -729,9 +739,14 @@ void main() { ...@@ -729,9 +739,14 @@ void main() {
// 4th, check that a non-default clip behavior can be sent to the painting context. // 4th, check that a non-default clip behavior can be sent to the painting context.
renderObject.paint(context, Offset.zero); renderObject.paint(context, Offset.zero);
expect(context.clipBehavior, equals(Clip.antiAlias)); expect(context.clipBehavior, equals(Clip.antiAlias));
}); },
leakTrackingTestConfig: const LeakTrackingTestConfig(
testWidgets('GridView.builder respects clipBehavior', (WidgetTester tester) async { // TODO(ksokolovskyi): remove after fixing
// https://github.com/flutter/flutter/issues/134572
notDisposedAllowList: <String, int?> {'ContainerLayer': 1},
));
testWidgetsWithLeakTracking('GridView.builder respects clipBehavior', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -747,7 +762,7 @@ void main() { ...@@ -747,7 +762,7 @@ void main() {
expect(renderObject.clipBehavior, equals(Clip.antiAlias)); 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( await tester.pumpWidget(
Directionality( Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -765,7 +780,7 @@ void main() { ...@@ -765,7 +780,7 @@ void main() {
expect(renderObject.clipBehavior, equals(Clip.antiAlias)); 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( await tester.pumpWidget(
Directionality( Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -780,7 +795,7 @@ void main() { ...@@ -780,7 +795,7 @@ void main() {
expect(renderObject.clipBehavior, equals(Clip.antiAlias)); 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( await tester.pumpWidget(
Directionality( Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -795,7 +810,7 @@ void main() { ...@@ -795,7 +810,7 @@ void main() {
expect(renderObject.clipBehavior, equals(Clip.antiAlias)); 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 int crossAxisCount = 4;
const double mainAxisExtent = 100.0; const double mainAxisExtent = 100.0;
...@@ -821,7 +836,7 @@ void main() { ...@@ -821,7 +836,7 @@ void main() {
expect(tester.getSize(find.text('4')), equals(const Size(200.0, mainAxisExtent))); 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 maxCrossAxisExtent = 200.0;
const double mainAxisExtent = 100.0; const double mainAxisExtent = 100.0;
...@@ -847,7 +862,7 @@ void main() { ...@@ -847,7 +862,7 @@ void main() {
expect(tester.getSize(find.text('4')), equals(const Size(200.0, mainAxisExtent))); 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; const double maxCrossAxisExtent = 0;
expect(() => Directionality( expect(() => Directionality(
...@@ -858,9 +873,10 @@ void main() { ...@@ -858,9 +873,10 @@ void main() {
), throwsAssertionError); ), 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 // Regression test for https://github.com/flutter/flutter/issues/130685
final ScrollController controller = ScrollController(); final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
await tester.pumpWidget(Directionality( await tester.pumpWidget(Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
child: GridView.builder( child: GridView.builder(
......
...@@ -9,6 +9,7 @@ import 'package:flutter/foundation.dart'; ...@@ -9,6 +9,7 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
import 'package:flutter_test/flutter_test.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; import '../painting/image_test_utils.dart' show TestImageProvider;
...@@ -190,7 +191,7 @@ Future<void> main() async { ...@@ -190,7 +191,7 @@ Future<void> main() async {
transitionFromUserGestures = false; transitionFromUserGestures = false;
}); });
testWidgets('Heroes animate', (WidgetTester tester) async { testWidgetsWithLeakTracking('Heroes animate', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(routes: routes)); await tester.pumpWidget(MaterialApp(routes: routes));
...@@ -300,7 +301,7 @@ Future<void> main() async { ...@@ -300,7 +301,7 @@ Future<void> main() async {
expect(find.byKey(thirdKey), isInCard); 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 GlobalKey<NavigatorState> key = GlobalKey<NavigatorState>();
final UniqueKey heroKey = UniqueKey(); final UniqueKey heroKey = UniqueKey();
await tester.pumpWidget( await tester.pumpWidget(
...@@ -395,7 +396,7 @@ Future<void> main() async { ...@@ -395,7 +396,7 @@ Future<void> main() async {
expect(find.byKey(heroKey), findsNothing); 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)); await tester.pumpWidget(MaterialApp(routes: routes));
// Checks initial state. // Checks initial state.
expect(find.byKey(firstKey), isOnstage); expect(find.byKey(firstKey), isOnstage);
...@@ -418,7 +419,7 @@ Future<void> main() async { ...@@ -418,7 +419,7 @@ Future<void> main() async {
expect(find.byKey(secondKey), isInCard); 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(); final MutatingRoute route = MutatingRoute();
await tester.pumpWidget(MaterialApp( await tester.pumpWidget(MaterialApp(
...@@ -443,7 +444,7 @@ Future<void> main() async { ...@@ -443,7 +444,7 @@ Future<void> main() async {
await tester.pump(const Duration(seconds: 1)); 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.pumpWidget(MaterialApp(routes: routes));
await tester.tap(find.text('two')); await tester.tap(find.text('two'));
await tester.pump(); // begin navigation await tester.pump(); // begin navigation
...@@ -483,7 +484,7 @@ Future<void> main() async { ...@@ -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>[]; final List<String> log = <String>[];
await tester.pumpWidget(MaterialApp( await tester.pumpWidget(MaterialApp(
...@@ -553,7 +554,7 @@ Future<void> main() async { ...@@ -553,7 +554,7 @@ Future<void> main() async {
expect(log, equals(<String>['bar'])); 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( await tester.pumpWidget(MaterialApp(
onGenerateRoute: (RouteSettings settings) { onGenerateRoute: (RouteSettings settings) {
return MaterialPageRoute<void>( return MaterialPageRoute<void>(
...@@ -574,7 +575,7 @@ Future<void> main() async { ...@@ -574,7 +575,7 @@ Future<void> main() async {
await tester.pump(); // ...and removes it straight away (since it's already at 0.0) 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( await tester.pumpWidget(MaterialApp(
onGenerateRoute: (RouteSettings settings) { onGenerateRoute: (RouteSettings settings) {
return MaterialPageRoute<void>( return MaterialPageRoute<void>(
...@@ -603,7 +604,7 @@ Future<void> main() async { ...@@ -603,7 +604,7 @@ Future<void> main() async {
await tester.pump(); 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( await tester.pumpWidget(MaterialApp(
home: Material( home: Material(
child: ListView( child: ListView(
...@@ -658,7 +659,7 @@ Future<void> main() async { ...@@ -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( await tester.pumpWidget(MaterialApp(
routes: routes, routes: routes,
)); ));
...@@ -723,7 +724,7 @@ Future<void> main() async { ...@@ -723,7 +724,7 @@ Future<void> main() async {
expect(find.byKey(secondKey), findsNothing); 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( await tester.pumpWidget(
MaterialApp( MaterialApp(
routes: routes, routes: routes,
...@@ -800,7 +801,7 @@ Future<void> main() async { ...@@ -800,7 +801,7 @@ Future<void> main() async {
expect(find.byKey(firstKey), findsNothing); 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 homeHeroKey = Key('home hero');
const Key routeHeroKey = Key('route hero'); const Key routeHeroKey = Key('route hero');
bool routeIncludesHero = true; bool routeIncludesHero = true;
...@@ -903,7 +904,7 @@ Future<void> main() async { ...@@ -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 homeHeroKey = Key('home hero');
const Key routeHeroKey = Key('route hero'); const Key routeHeroKey = Key('route hero');
const Key routeContainerKey = Key('route hero container'); const Key routeContainerKey = Key('route hero container');
...@@ -990,7 +991,7 @@ Future<void> main() async { ...@@ -990,7 +991,7 @@ Future<void> main() async {
expect(finalHeroY, 75.0); // 100 less 25 for the scroll 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 homeHeroKey = Key('home hero');
const Key routeHeroKey = Key('route hero'); const Key routeHeroKey = Key('route hero');
const Key routeContainerKey = Key('route hero container'); const Key routeContainerKey = Key('route hero container');
...@@ -1067,7 +1068,7 @@ Future<void> main() async { ...@@ -1067,7 +1068,7 @@ Future<void> main() async {
expect(find.byKey(routeHeroKey), findsNothing); 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 // See https://github.com/flutter/flutter/issues/5798
const Key heroABKey = Key('AB hero'); const Key heroABKey = Key('AB hero');
const Key heroBCKey = Key('BC hero'); const Key heroBCKey = Key('BC hero');
...@@ -1202,7 +1203,7 @@ Future<void> main() async { ...@@ -1202,7 +1203,7 @@ Future<void> main() async {
expect(tester.getTopLeft(find.byKey(heroBCKey)).dy, 0.0); 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>( final MaterialPageRoute<void> route = MaterialPageRoute<void>(
builder: (BuildContext context) { builder: (BuildContext context) {
return Material( return Material(
...@@ -1286,7 +1287,7 @@ Future<void> main() async { ...@@ -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) { RectTween createRectTween(Rect? begin, Rect? end) {
return MaterialRectCenterArcTween(begin: begin, end: end); return MaterialRectCenterArcTween(begin: begin, end: end);
} }
...@@ -1398,7 +1399,7 @@ Future<void> main() async { ...@@ -1398,7 +1399,7 @@ Future<void> main() async {
expect(tester.getCenter(find.byKey(firstKey)), const Offset(50.0, 50.0)); 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 // Regression test for https://github.com/flutter/flutter/issues/25272
RectTween createRectTween(Rect? begin, Rect? end) { RectTween createRectTween(Rect? begin, Rect? end) {
...@@ -1519,7 +1520,7 @@ Future<void> main() async { ...@@ -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.pumpWidget(MaterialApp(routes: routes));
await tester.tap(find.text('twoInset')); await tester.tap(find.text('twoInset'));
await tester.pump(); // begin navigation from / to /twoInset. await tester.pump(); // begin navigation from / to /twoInset.
...@@ -1612,7 +1613,7 @@ Future<void> main() async { ...@@ -1612,7 +1613,7 @@ Future<void> main() async {
expect(tester.getTopLeft(find.byKey(firstKey)).dx, x0); 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( await tester.pumpWidget(MaterialApp(
home: Material( home: Material(
child: ListView( child: ListView(
...@@ -1656,7 +1657,7 @@ Future<void> main() async { ...@@ -1656,7 +1657,7 @@ Future<void> main() async {
expect(find.text('baz'), findsOneWidget); 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( await tester.pumpWidget(MaterialApp(
home: Material( home: Material(
child: ListView( child: ListView(
...@@ -1699,7 +1700,7 @@ Future<void> main() async { ...@@ -1699,7 +1700,7 @@ Future<void> main() async {
}); });
// Regression test for https://github.com/flutter/flutter/issues/77720. // 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( await tester.pumpWidget(MaterialApp(
home: Material( home: Material(
child: ListView( child: ListView(
...@@ -1752,7 +1753,7 @@ Future<void> main() async { ...@@ -1752,7 +1753,7 @@ Future<void> main() async {
expect(find.text('toHero text'), findsOneWidget); 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( await tester.pumpWidget(MaterialApp(
home: Material( home: Material(
child: ListView( child: ListView(
...@@ -1799,7 +1800,7 @@ Future<void> main() async { ...@@ -1799,7 +1800,7 @@ Future<void> main() async {
expect(find.text('Joker'), findsOneWidget); 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( await tester.pumpWidget(MaterialApp(
routes: routes, routes: routes,
)); ));
...@@ -1838,7 +1839,7 @@ Future<void> main() async { ...@@ -1838,7 +1839,7 @@ Future<void> main() async {
expect(find.byKey(secondKey), isInCard); expect(find.byKey(secondKey), isInCard);
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS })); }, 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; transitionFromUserGestures = true;
await tester.pumpWidget(MaterialApp( await tester.pumpWidget(MaterialApp(
routes: routes, routes: routes,
...@@ -1881,7 +1882,7 @@ Future<void> main() async { ...@@ -1881,7 +1882,7 @@ Future<void> main() async {
expect(find.byKey(secondKey), findsNothing); expect(find.byKey(secondKey), findsNothing);
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS })); }, 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; transitionFromUserGestures = true;
await tester.pumpWidget(MaterialApp( await tester.pumpWidget(MaterialApp(
routes: routes, routes: routes,
...@@ -1917,7 +1918,7 @@ Future<void> main() async { ...@@ -1917,7 +1918,7 @@ Future<void> main() async {
expect(find.byKey(secondKey), isInCard); expect(find.byKey(secondKey), isInCard);
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS })); }, 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( await tester.pumpWidget(MaterialApp(
routes: routes, routes: routes,
initialRoute: '/two', initialRoute: '/two',
...@@ -1927,7 +1928,7 @@ Future<void> main() async { ...@@ -1927,7 +1928,7 @@ Future<void> main() async {
expect(find.text('three'), findsOneWidget); 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. // Regression test for https://github.com/flutter/flutter/issues/28042.
const String heroTag = 'You are my hero!'; const String heroTag = 'You are my hero!';
...@@ -2001,7 +2002,7 @@ Future<void> main() async { ...@@ -2001,7 +2002,7 @@ Future<void> main() async {
expect(find.byKey(nestedRouteHeroBottom, skipOffstage: false), findsOneWidget); 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'; const String heroTag = 'foo';
final GlobalKey<NavigatorState> rootNavigator = GlobalKey(); final GlobalKey<NavigatorState> rootNavigator = GlobalKey();
final Key smallContainer = UniqueKey(); final Key smallContainer = UniqueKey();
...@@ -2087,7 +2088,7 @@ Future<void> main() async { ...@@ -2087,7 +2088,7 @@ Future<void> main() async {
expect(tester.getSize(find.byKey(smallContainer)), const Size(100,100)); 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( await tester.pumpWidget(
const MaterialApp( const MaterialApp(
home: Material( home: Material(
...@@ -2105,7 +2106,7 @@ Future<void> main() async { ...@@ -2105,7 +2106,7 @@ Future<void> main() async {
expect(tester.takeException(), isAssertionError); 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'; const String heroTag = 'foo';
final GlobalKey<NavigatorState> rootNavigator = GlobalKey<NavigatorState>(); final GlobalKey<NavigatorState> rootNavigator = GlobalKey<NavigatorState>();
final Key rootRouteHero = UniqueKey(); final Key rootRouteHero = UniqueKey();
...@@ -2189,7 +2190,7 @@ Future<void> main() async { ...@@ -2189,7 +2190,7 @@ Future<void> main() async {
expect(find.byKey(nestedRouteHeroOne, skipOffstage: false), findsOneWidget); 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( await tester.pumpWidget(
const MaterialApp( const MaterialApp(
home: Material( home: Material(
...@@ -2207,7 +2208,7 @@ Future<void> main() async { ...@@ -2207,7 +2208,7 @@ Future<void> main() async {
expect(tester.takeException(), isAssertionError); 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( await tester.pumpWidget(
MaterialApp( MaterialApp(
home: Material( home: Material(
...@@ -2229,7 +2230,7 @@ Future<void> main() async { ...@@ -2229,7 +2230,7 @@ Future<void> main() async {
expect(tester.takeException(),isAssertionError); 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( await tester.pumpWidget(
MaterialApp( MaterialApp(
home: Material( home: Material(
...@@ -2251,7 +2252,7 @@ Future<void> main() async { ...@@ -2251,7 +2252,7 @@ Future<void> main() async {
expect(tester.takeException(), isAssertionError); 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. // Regression test for https://github.com/flutter/flutter/issues/28041.
const String heroTag = 'foo'; const String heroTag = 'foo';
...@@ -2338,7 +2339,7 @@ Future<void> main() async { ...@@ -2338,7 +2339,7 @@ Future<void> main() async {
expect(tester.getSize(find.byKey(smallContainer)), const Size(100,100)); 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; int shuttlesBuilt = 0;
Widget shuttleBuilder( Widget shuttleBuilder(
BuildContext flightContext, BuildContext flightContext,
...@@ -2401,7 +2402,7 @@ Future<void> main() async { ...@@ -2401,7 +2402,7 @@ Future<void> main() async {
expect(shuttlesBuilt, 2); expect(shuttlesBuilt, 2);
}); });
testWidgets( testWidgetsWithLeakTracking(
"From hero's state should be preserved, " "From hero's state should be preserved, "
'heroes work well with child widgets that has global keys', 'heroes work well with child widgets that has global keys',
(WidgetTester tester) async { (WidgetTester tester) async {
...@@ -2468,7 +2469,7 @@ Future<void> main() async { ...@@ -2468,7 +2469,7 @@ Future<void> main() async {
}, },
); );
testWidgets( testWidgetsWithLeakTracking(
"Hero works with images that don't have both width and height specified", "Hero works with images that don't have both width and height specified",
// Regression test for https://github.com/flutter/flutter/issues/32356 // Regression test for https://github.com/flutter/flutter/issues/32356
// and https://github.com/flutter/flutter/issues/31503 // and https://github.com/flutter/flutter/issues/31503
...@@ -2556,7 +2557,7 @@ Future<void> main() async { ...@@ -2556,7 +2557,7 @@ Future<void> main() async {
); );
// Regression test for https://github.com/flutter/flutter/issues/38183. // 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; transitionFromUserGestures = true;
await tester.pumpWidget(MaterialApp( await tester.pumpWidget(MaterialApp(
routes: routes, routes: routes,
...@@ -2585,7 +2586,7 @@ Future<void> main() async { ...@@ -2585,7 +2586,7 @@ Future<void> main() async {
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS })); }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
// Regression test for https://github.com/flutter/flutter/issues/40239. // 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', 'In a pop transition, when fromHero is null, the to hero should eventually become visible',
(WidgetTester tester) async { (WidgetTester tester) async {
final GlobalKey<NavigatorState> navigatorKey = GlobalKey(); final GlobalKey<NavigatorState> navigatorKey = GlobalKey();
...@@ -2634,7 +2635,7 @@ Future<void> main() async { ...@@ -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 container1 = UniqueKey();
final Key container2 = UniqueKey(); final Key container2 = UniqueKey();
final GlobalKey<NavigatorState> navigator = GlobalKey<NavigatorState>(); final GlobalKey<NavigatorState> navigator = GlobalKey<NavigatorState>();
...@@ -2712,7 +2713,7 @@ Future<void> main() async { ...@@ -2712,7 +2713,7 @@ Future<void> main() async {
expect(heroSize, tween.transform(1.0)); 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( await tester.pumpWidget(MaterialApp(
home: Material( home: Material(
child: Column( child: Column(
...@@ -2783,7 +2784,7 @@ Future<void> main() async { ...@@ -2783,7 +2784,7 @@ Future<void> main() async {
expect(find.byKey(secondKey), isInCard); 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( await tester.pumpWidget(MaterialApp(
home: Material( home: Material(
child: Column( child: Column(
...@@ -2861,7 +2862,7 @@ Future<void> main() async { ...@@ -2861,7 +2862,7 @@ Future<void> main() async {
expect(find.byKey(secondKey), isOnstage); 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>(); final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
await tester.pumpWidget( await tester.pumpWidget(
...@@ -2914,9 +2915,10 @@ Future<void> main() async { ...@@ -2914,9 +2915,10 @@ Future<void> main() async {
expect(find.byType(Placeholder), findsOneWidget); 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 GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
final ScrollController controller = ScrollController(); final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
RenderAnimatedOpacity? findRenderAnimatedOpacity() { RenderAnimatedOpacity? findRenderAnimatedOpacity() {
RenderObject? parent = tester.renderObject(find.byType(Placeholder)); RenderObject? parent = tester.renderObject(find.byType(Placeholder));
...@@ -2989,7 +2991,7 @@ Future<void> main() async { ...@@ -2989,7 +2991,7 @@ Future<void> main() async {
expect(find.byType(Placeholder), findsNothing); 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>(); final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
await tester.pumpWidget( await tester.pumpWidget(
...@@ -3069,7 +3071,7 @@ Future<void> main() async { ...@@ -3069,7 +3071,7 @@ Future<void> main() async {
expect(tester.takeException(), isNull); 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); addTearDown(tester.view.reset);
final GlobalKey<NavigatorState> navigatorKey = GlobalKey(); final GlobalKey<NavigatorState> navigatorKey = GlobalKey();
......
...@@ -6,16 +6,17 @@ import 'package:flutter/gestures.dart'; ...@@ -6,16 +6,17 @@ import 'package:flutter/gestures.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
void main() { 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))); await tester.pumpWidget(const Center(child: Text('Hello', textDirection: TextDirection.ltr)));
final HitTestResult result = tester.hitTestOnBinding(Offset.zero); final HitTestResult result = tester.hitTestOnBinding(Offset.zero);
expect(result, hasOneLineDescription); expect(result, hasOneLineDescription);
expect(result.path.first, 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; int hitCount = 0;
await tester.pumpWidget( await tester.pumpWidget(
_HitTestCounter( _HitTestCounter(
...@@ -31,7 +32,7 @@ void main() { ...@@ -31,7 +32,7 @@ void main() {
expect(hitCount, 1); 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; int hitCount = 0;
await tester.pumpWidget( await tester.pumpWidget(
_HitTestCounter( _HitTestCounter(
......
...@@ -5,9 +5,10 @@ ...@@ -5,9 +5,10 @@
import 'package:flutter/gestures.dart'; import 'package:flutter/gestures.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
void main() { void main() {
testWidgets('Can tap a hyperlink', (WidgetTester tester) async { testWidgetsWithLeakTracking('Can tap a hyperlink', (WidgetTester tester) async {
bool didTapLeft = false; bool didTapLeft = false;
final TapGestureRecognizer tapLeft = TapGestureRecognizer() final TapGestureRecognizer tapLeft = TapGestureRecognizer()
..onTap = () { ..onTap = () {
......
...@@ -6,11 +6,12 @@ import 'dart:ui'; ...@@ -6,11 +6,12 @@ import 'dart:ui';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
import 'semantics_tester.dart'; import 'semantics_tester.dart';
void main() { 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( await tester.pumpWidget(
const Directionality( const Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -27,7 +28,7 @@ void main() { ...@@ -27,7 +28,7 @@ void main() {
expect(text.text.style!.color, const Color(0xFF666666).withOpacity(0.5)); 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( await tester.pumpWidget(
const Directionality( const Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -41,7 +42,7 @@ void main() { ...@@ -41,7 +42,7 @@ void main() {
expect(renderObject.size, equals(const Size.square(24.0))); 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( await tester.pumpWidget(
const Directionality( const Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -58,7 +59,7 @@ void main() { ...@@ -58,7 +59,7 @@ void main() {
expect(renderObject.size, equals(const Size.square(96.0))); 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( await tester.pumpWidget(
const Directionality( const Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -75,7 +76,7 @@ void main() { ...@@ -75,7 +76,7 @@ void main() {
expect(renderObject.size, equals(const Size.square(36.0))); 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( await tester.pumpWidget(
const Directionality( const Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -95,7 +96,7 @@ void main() { ...@@ -95,7 +96,7 @@ void main() {
expect(renderObject.size, equals(const Size.square(48.0))); 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( await tester.pumpWidget(
const Directionality( const Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -113,7 +114,7 @@ void main() { ...@@ -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( await tester.pumpWidget(
const Directionality( const Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -127,7 +128,7 @@ void main() { ...@@ -127,7 +128,7 @@ void main() {
expect(richText.text.style!.fontFamily, equals('Roboto')); 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( await tester.pumpWidget(
const Directionality( const Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -141,7 +142,7 @@ void main() { ...@@ -141,7 +142,7 @@ void main() {
expect(richText.text.style!.fontFamilyFallback, equals(<String>['FallbackFont'])); 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); final SemanticsTester semantics = SemanticsTester(tester);
await tester.pumpWidget( await tester.pumpWidget(
...@@ -161,7 +162,7 @@ void main() { ...@@ -161,7 +162,7 @@ void main() {
semantics.dispose(); 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); final SemanticsTester semantics = SemanticsTester(tester);
await tester.pumpWidget( await tester.pumpWidget(
...@@ -181,7 +182,7 @@ void main() { ...@@ -181,7 +182,7 @@ void main() {
semantics.dispose(); 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( await tester.pumpWidget(
const Directionality( const Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -212,7 +213,7 @@ void main() { ...@@ -212,7 +213,7 @@ void main() {
expect(richText2, same(richText1)); 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), const IconData(123));
expect(const IconData(123), isNot(const IconData(123, matchTextDirection: true))); expect(const IconData(123), isNot(const IconData(123, matchTextDirection: true)));
expect(const IconData(123), isNot(const IconData(123, fontFamily: 'f'))); expect(const IconData(123), isNot(const IconData(123, fontFamily: 'f')));
...@@ -225,7 +226,7 @@ void main() { ...@@ -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( await tester.pumpWidget(
const Directionality( const Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -258,7 +259,7 @@ void main() { ...@@ -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( await tester.pumpWidget(
const Directionality( const Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -283,7 +284,7 @@ void main() { ...@@ -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( await tester.pumpWidget(
const Directionality( const Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
......
...@@ -13,17 +13,18 @@ import 'dart:ui' as ui; ...@@ -13,17 +13,18 @@ import 'dart:ui' as ui;
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
void main() { void main() {
testWidgets('Image at default filterQuality', (WidgetTester tester) async { testWidgetsWithLeakTracking('Image at default filterQuality', (WidgetTester tester) async {
await testImageQuality(tester, null); 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); 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); await testImageQuality(tester, ui.FilterQuality.none);
}); });
} }
......
...@@ -14,9 +14,10 @@ import 'package:flutter/foundation.dart'; ...@@ -14,9 +14,10 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
void main() { void main() {
testWidgets('Image filter - blur', (WidgetTester tester) async { testWidgetsWithLeakTracking('Image filter - blur', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
RepaintBoundary( RepaintBoundary(
child: ImageFiltered( child: ImageFiltered(
...@@ -31,7 +32,7 @@ void main() { ...@@ -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(); final Key key = GlobalKey();
await tester.pumpWidget( await tester.pumpWidget(
RepaintBoundary( RepaintBoundary(
...@@ -51,7 +52,7 @@ void main() { ...@@ -51,7 +52,7 @@ void main() {
); );
}); });
testWidgets('Image filter - dilate', (WidgetTester tester) async { testWidgetsWithLeakTracking('Image filter - dilate', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
RepaintBoundary( RepaintBoundary(
child: ImageFiltered( child: ImageFiltered(
...@@ -66,7 +67,7 @@ void main() { ...@@ -66,7 +67,7 @@ void main() {
); );
}, skip: kIsWeb); // https://github.com/flutter/flutter/issues/101874 }, 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( await tester.pumpWidget(
RepaintBoundary( RepaintBoundary(
child: ImageFiltered( child: ImageFiltered(
...@@ -82,7 +83,7 @@ void main() { ...@@ -82,7 +83,7 @@ void main() {
); );
}, skip: kIsWeb); // https://github.com/flutter/flutter/issues/101874 }, 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>[ final ImageFilter matrix = ImageFilter.matrix(Float64List.fromList(<double>[
0.5, 0.0, 0.0, 0.0, // 0.5, 0.0, 0.0, 0.0, //
0.0, 0.5, 0.0, 0.0, // 0.0, 0.5, 0.0, 0.0, //
...@@ -119,7 +120,7 @@ void main() { ...@@ -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 Matrix4 matrix = Matrix4.rotationZ(pi / 18);
final ImageFilter matrixFilter = ImageFilter.matrix(matrix.storage); final ImageFilter matrixFilter = ImageFilter.matrix(matrix.storage);
final Key key = GlobalKey(); final Key key = GlobalKey();
...@@ -157,7 +158,7 @@ void main() { ...@@ -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 { Future<void> pumpWithSigma(double sigma) async {
await tester.pumpWidget( await tester.pumpWidget(
RepaintBoundary( RepaintBoundary(
...@@ -178,7 +179,7 @@ void main() { ...@@ -178,7 +179,7 @@ void main() {
expect(renderObject.debugLayer, same(originalLayer)); 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 { Future<void> pumpWithEnabledState(bool enabled) async {
await tester.pumpWidget( await tester.pumpWidget(
RepaintBoundary( RepaintBoundary(
......
...@@ -7,13 +7,14 @@ import 'dart:io'; ...@@ -7,13 +7,14 @@ import 'dart:io';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
import '../image_data.dart'; import '../image_data.dart';
void main() { void main() {
final MockHttpClient client = MockHttpClient(); final MockHttpClient client = MockHttpClient();
testWidgets('Headers', (WidgetTester tester) async { testWidgetsWithLeakTracking('Headers', (WidgetTester tester) async {
HttpOverrides.runZoned<Future<void>>(() async { HttpOverrides.runZoned<Future<void>>(() async {
await tester.pumpWidget(Image.network( await tester.pumpWidget(Image.network(
'https://www.example.com/images/frame.png', 'https://www.example.com/images/frame.png',
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.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'; import '../painting/mocks_for_image_cache.dart';
...@@ -20,7 +21,7 @@ void main() { ...@@ -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( await tester.pumpWidget(
Center( Center(
child: ImageIcon(image), child: ImageIcon(image),
...@@ -32,7 +33,7 @@ void main() { ...@@ -32,7 +33,7 @@ void main() {
expect(find.byType(Image), findsOneWidget); expect(find.byType(Image), findsOneWidget);
}); });
testWidgets('Icon opacity', (WidgetTester tester) async { testWidgetsWithLeakTracking('Icon opacity', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
Center( Center(
child: IconTheme( child: IconTheme(
...@@ -45,7 +46,7 @@ void main() { ...@@ -45,7 +46,7 @@ void main() {
expect(tester.widget<Image>(find.byType(Image)).color!.alpha, equals(128)); 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( await tester.pumpWidget(
const Center( const Center(
child: ImageIcon( child: ImageIcon(
...@@ -59,7 +60,7 @@ void main() { ...@@ -59,7 +60,7 @@ void main() {
expect(renderObject.size, equals(const Size.square(96.0))); 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( await tester.pumpWidget(
const Center( const Center(
child: IconTheme( child: IconTheme(
...@@ -73,7 +74,7 @@ void main() { ...@@ -73,7 +74,7 @@ void main() {
expect(renderObject.size, equals(const Size.square(36.0))); 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( await tester.pumpWidget(
const Center( const Center(
child: IconTheme( child: IconTheme(
...@@ -90,7 +91,7 @@ void main() { ...@@ -90,7 +91,7 @@ void main() {
expect(renderObject.size, equals(const Size.square(48.0))); 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( await tester.pumpWidget(
const Center( const Center(
child: IconTheme( child: IconTheme(
...@@ -104,7 +105,7 @@ void main() { ...@@ -104,7 +105,7 @@ void main() {
expect(renderObject.size, equals(const Size.square(24.0))); 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(); final SemanticsHandle handle = tester.ensureSemantics();
await tester.pumpWidget( await tester.pumpWidget(
const Directionality( const Directionality(
......
...@@ -13,6 +13,7 @@ import 'package:flutter/rendering.dart'; ...@@ -13,6 +13,7 @@ import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
import '../image_data.dart'; import '../image_data.dart';
...@@ -155,6 +156,7 @@ void main() { ...@@ -155,6 +156,7 @@ void main() {
const String image = 'assets/image.png'; const String image = 'assets/image.png';
final Map<double, ui.Image> images = <double, ui.Image>{}; final Map<double, ui.Image> images = <double, ui.Image>{};
setUpAll(() async { setUpAll(() async {
for (final double scale in const <double>[0.5, 1.0, 1.5, 2.0, 4.0, 10.0]) { 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(); final int dimension = (48 * scale).floor();
...@@ -162,7 +164,13 @@ void main() { ...@@ -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; const double ratio = 1.0;
Key key = GlobalKey(); Key key = GlobalKey();
await pumpTreeToLayout(tester, buildImageAtRatio(image, key, ratio, false, images)); await pumpTreeToLayout(tester, buildImageAtRatio(image, key, ratio, false, images));
...@@ -174,7 +182,7 @@ void main() { ...@@ -174,7 +182,7 @@ void main() {
expect(getRenderImage(tester, key).scale, 1.0); 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; const double ratio = 0.5;
Key key = GlobalKey(); Key key = GlobalKey();
await pumpTreeToLayout(tester, buildImageAtRatio(image, key, ratio, false, images)); await pumpTreeToLayout(tester, buildImageAtRatio(image, key, ratio, false, images));
...@@ -186,7 +194,7 @@ void main() { ...@@ -186,7 +194,7 @@ void main() {
expect(getRenderImage(tester, key).scale, 1.0); 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; const double ratio = 1.5;
Key key = GlobalKey(); Key key = GlobalKey();
await pumpTreeToLayout(tester, buildImageAtRatio(image, key, ratio, false, images)); await pumpTreeToLayout(tester, buildImageAtRatio(image, key, ratio, false, images));
...@@ -201,7 +209,7 @@ void main() { ...@@ -201,7 +209,7 @@ void main() {
// A 1.75 DPR screen is typically a low-resolution screen, such that physical // 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 // pixels are visible to the user. For such screens we prefer to pick the
// higher resolution image, if available. // 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; const double ratio = 1.75;
Key key = GlobalKey(); Key key = GlobalKey();
await pumpTreeToLayout(tester, buildImageAtRatio(image, key, ratio, false, images)); await pumpTreeToLayout(tester, buildImageAtRatio(image, key, ratio, false, images));
...@@ -213,7 +221,7 @@ void main() { ...@@ -213,7 +221,7 @@ void main() {
expect(getRenderImage(tester, key).scale, 2.0); 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; const double ratio = 2.3;
Key key = GlobalKey(); Key key = GlobalKey();
await pumpTreeToLayout(tester, buildImageAtRatio(image, key, ratio, false, images)); await pumpTreeToLayout(tester, buildImageAtRatio(image, key, ratio, false, images));
...@@ -225,7 +233,7 @@ void main() { ...@@ -225,7 +233,7 @@ void main() {
expect(getRenderImage(tester, key).scale, 2.0); 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; const double ratio = 3.7;
Key key = GlobalKey(); Key key = GlobalKey();
await pumpTreeToLayout(tester, buildImageAtRatio(image, key, ratio, false, images)); await pumpTreeToLayout(tester, buildImageAtRatio(image, key, ratio, false, images));
...@@ -237,7 +245,7 @@ void main() { ...@@ -237,7 +245,7 @@ void main() {
expect(getRenderImage(tester, key).scale, 4.0); 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; const double ratio = 5.1;
Key key = GlobalKey(); Key key = GlobalKey();
await pumpTreeToLayout(tester, buildImageAtRatio(image, key, ratio, false, images)); await pumpTreeToLayout(tester, buildImageAtRatio(image, key, ratio, false, images));
...@@ -249,7 +257,7 @@ void main() { ...@@ -249,7 +257,7 @@ void main() {
expect(getRenderImage(tester, key).scale, 4.0); 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 // If both a main asset and a 1.0x asset are specified, then prefer
// the 1.0x asset. // the 1.0x asset.
...@@ -279,19 +287,19 @@ void main() { ...@@ -279,19 +287,19 @@ void main() {
expect(getRenderImage(tester, key).image!.height, 480); 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(); final Key key = GlobalKey();
await pumpTreeToLayout(tester, buildImageCacheResized(image, key, 5, 5, 20, 20)); await pumpTreeToLayout(tester, buildImageCacheResized(image, key, 5, 5, 20, 20));
expect(getRenderImage(tester, key).size, const Size(5.0, 5.0)); 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(); final Key key = GlobalKey();
await pumpTreeToLayout(tester, buildImageCacheResized(image, key, 50, 50, 20, 20)); await pumpTreeToLayout(tester, buildImageCacheResized(image, key, 50, 50, 20, 20));
expect(getRenderImage(tester, key).size, const Size(50.0, 50.0)); 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(); final Key key = GlobalKey();
await pumpTreeToLayout(tester, buildImageCacheResized(image, key, 5, 5, 1, 1)); await pumpTreeToLayout(tester, buildImageCacheResized(image, key, 5, 5, 1, 1));
expect(getRenderImage(tester, key).size, const Size(5.0, 5.0)); expect(getRenderImage(tester, key).size, const Size(5.0, 5.0));
...@@ -301,7 +309,7 @@ void main() { ...@@ -301,7 +309,7 @@ void main() {
// visible physical pixel size (see the test for 1.75 DPR above). However, // 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 // if higher resolution assets are not available we will pick the best
// available. // available.
testWidgets('Low-resolution assets', (WidgetTester tester) async { testWidgetsWithLeakTracking('Low-resolution assets', (WidgetTester tester) async {
const Map<Object?, Object?> manifest = <Object?, Object?>{ const Map<Object?, Object?> manifest = <Object?, Object?>{
'assets/image.png': <Map<String, Object>>[ 'assets/image.png': <Map<String, Object>>[
<String, Object>{'asset': 'assets/image.png'}, <String, Object>{'asset': 'assets/image.png'},
......
...@@ -7,6 +7,7 @@ import 'dart:ui' as ui show Image; ...@@ -7,6 +7,7 @@ import 'dart:ui' as ui show Image;
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
class TestImageProvider extends ImageProvider<TestImageProvider> { class TestImageProvider extends ImageProvider<TestImageProvider> {
const TestImageProvider(this.image); const TestImageProvider(this.image);
...@@ -28,10 +29,16 @@ class TestImageProvider extends ImageProvider<TestImageProvider> { ...@@ -28,10 +29,16 @@ class TestImageProvider extends ImageProvider<TestImageProvider> {
void main() { void main() {
late ui.Image testImage; late ui.Image testImage;
setUpAll(() async { setUpAll(() async {
testImage = await createTestImage(width: 16, height: 9); 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( await tester.pumpWidget(
Directionality( Directionality(
textDirection: TextDirection.rtl, textDirection: TextDirection.rtl,
...@@ -70,7 +77,7 @@ void main() { ...@@ -70,7 +77,7 @@ void main() {
expect(find.byType(Container), isNot(paints..scale()..scale())); 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( await tester.pumpWidget(
Directionality( Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -106,7 +113,7 @@ void main() { ...@@ -106,7 +113,7 @@ void main() {
expect(find.byType(Container), isNot(paints..scale())); 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( await tester.pumpWidget(
Directionality( Directionality(
textDirection: TextDirection.rtl, textDirection: TextDirection.rtl,
...@@ -141,7 +148,7 @@ void main() { ...@@ -141,7 +148,7 @@ void main() {
expect(find.byType(Container), isNot(paints..scale())); 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( await tester.pumpWidget(
Directionality( Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -176,7 +183,7 @@ void main() { ...@@ -176,7 +183,7 @@ void main() {
expect(find.byType(Container), isNot(paints..scale())); 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( await tester.pumpWidget(
Directionality( Directionality(
textDirection: TextDirection.rtl, textDirection: TextDirection.rtl,
...@@ -208,7 +215,7 @@ void main() { ...@@ -208,7 +215,7 @@ void main() {
expect(find.byType(Container), isNot(paints..drawImageRect()..drawImageRect())); 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( await tester.pumpWidget(
Directionality( Directionality(
textDirection: TextDirection.rtl, textDirection: TextDirection.rtl,
...@@ -235,7 +242,7 @@ void main() { ...@@ -235,7 +242,7 @@ void main() {
expect(find.byType(Container), isNot(paints..drawImageRect()..drawImageRect())); 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( await tester.pumpWidget(
Directionality( Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -263,7 +270,7 @@ void main() { ...@@ -263,7 +270,7 @@ void main() {
expect(find.byType(Container), isNot(paints..drawImageRect()..drawImageRect())); 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( await tester.pumpWidget(
Directionality( Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -291,7 +298,7 @@ void main() { ...@@ -291,7 +298,7 @@ void main() {
expect(find.byType(Container), isNot(paints..drawImageRect()..drawImageRect())); 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( await tester.pumpWidget(
Directionality( Directionality(
textDirection: TextDirection.rtl, textDirection: TextDirection.rtl,
...@@ -328,7 +335,7 @@ void main() { ...@@ -328,7 +335,7 @@ void main() {
expect(find.byType(SizedBox), isNot(paints..scale()..scale())); 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( await tester.pumpWidget(
Directionality( Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -362,7 +369,7 @@ void main() { ...@@ -362,7 +369,7 @@ void main() {
expect(find.byType(SizedBox), isNot(paints..scale())); 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( await tester.pumpWidget(
Directionality( Directionality(
textDirection: TextDirection.rtl, textDirection: TextDirection.rtl,
...@@ -395,7 +402,7 @@ void main() { ...@@ -395,7 +402,7 @@ void main() {
expect(find.byType(SizedBox), isNot(paints..scale())); 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( await tester.pumpWidget(
Directionality( Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -428,7 +435,7 @@ void main() { ...@@ -428,7 +435,7 @@ void main() {
expect(find.byType(SizedBox), isNot(paints..scale())); 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( await tester.pumpWidget(
Directionality( Directionality(
textDirection: TextDirection.rtl, textDirection: TextDirection.rtl,
...@@ -456,7 +463,7 @@ void main() { ...@@ -456,7 +463,7 @@ void main() {
expect(find.byType(SizedBox), isNot(paints..drawImageRect()..drawImageRect())); 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( await tester.pumpWidget(
Directionality( Directionality(
textDirection: TextDirection.rtl, textDirection: TextDirection.rtl,
...@@ -481,7 +488,7 @@ void main() { ...@@ -481,7 +488,7 @@ void main() {
expect(find.byType(SizedBox), isNot(paints..drawImageRect()..drawImageRect())); 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( await tester.pumpWidget(
Directionality( Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -507,7 +514,7 @@ void main() { ...@@ -507,7 +514,7 @@ void main() {
expect(find.byType(SizedBox), isNot(paints..drawImageRect()..drawImageRect())); 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( await tester.pumpWidget(
Directionality( Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -533,7 +540,7 @@ void main() { ...@@ -533,7 +540,7 @@ void main() {
expect(find.byType(SizedBox), isNot(paints..drawImageRect()..drawImageRect())); 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( await tester.pumpWidget(
Directionality( Directionality(
textDirection: TextDirection.ltr, 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