Unverified Commit 78367258 authored by derdilla's avatar derdilla Committed by GitHub

Test cover cupertino text field for memory leaks. (#135804)

parent cfe7afdc
...@@ -17,6 +17,7 @@ import 'package:flutter/material.dart'; ...@@ -17,6 +17,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';
import '../widgets/clipboard_utils.dart'; import '../widgets/clipboard_utils.dart';
import '../widgets/editable_text_utils.dart' show OverflowWidgetTextEditingController; import '../widgets/editable_text_utils.dart' show OverflowWidgetTextEditingController;
...@@ -208,15 +209,17 @@ void main() { ...@@ -208,15 +209,17 @@ void main() {
}); });
testWidgets( testWidgetsWithLeakTracking(
'Live Text button shows and hides correctly when LiveTextStatus changes', 'Live Text button shows and hides correctly when LiveTextStatus changes',
(WidgetTester tester) async { (WidgetTester tester) async {
final LiveTextInputTester liveTextInputTester = LiveTextInputTester(); final LiveTextInputTester liveTextInputTester = LiveTextInputTester();
addTearDown(liveTextInputTester.dispose); addTearDown(liveTextInputTester.dispose);
final TextEditingController controller = TextEditingController(text: ''); final TextEditingController controller = TextEditingController(text: '');
addTearDown(controller.dispose);
const Key key = ValueKey<String>('TextField'); const Key key = ValueKey<String>('TextField');
final FocusNode focusNode = FocusNode(); final FocusNode focusNode = FocusNode();
addTearDown(focusNode.dispose);
final Widget app = MaterialApp( final Widget app = MaterialApp(
theme: ThemeData(platform: TargetPlatform.iOS), theme: ThemeData(platform: TargetPlatform.iOS),
home: Scaffold( home: Scaffold(
...@@ -250,7 +253,7 @@ void main() { ...@@ -250,7 +253,7 @@ void main() {
}, },
); );
testWidgets('Look Up shows up on iOS only', (WidgetTester tester) async { testWidgetsWithLeakTracking('Look Up shows up on iOS only', (WidgetTester tester) async {
String? lastLookUp; String? lastLookUp;
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
.setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async { .setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async {
...@@ -264,6 +267,7 @@ void main() { ...@@ -264,6 +267,7 @@ void main() {
final TextEditingController controller = TextEditingController( final TextEditingController controller = TextEditingController(
text: 'Test', text: 'Test',
); );
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
home: Center( home: Center(
...@@ -299,7 +303,7 @@ void main() { ...@@ -299,7 +303,7 @@ void main() {
skip: isContextMenuProvidedByPlatform, // [intended] only applies to platforms where we supply the context menu. skip: isContextMenuProvidedByPlatform, // [intended] only applies to platforms where we supply the context menu.
); );
testWidgets('Search Web shows up on iOS only', (WidgetTester tester) async { testWidgetsWithLeakTracking('Search Web shows up on iOS only', (WidgetTester tester) async {
String? lastSearch; String? lastSearch;
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
.setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async { .setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async {
...@@ -313,6 +317,7 @@ void main() { ...@@ -313,6 +317,7 @@ void main() {
final TextEditingController controller = TextEditingController( final TextEditingController controller = TextEditingController(
text: 'Test', text: 'Test',
); );
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
home: Center( home: Center(
...@@ -348,7 +353,7 @@ void main() { ...@@ -348,7 +353,7 @@ void main() {
skip: isContextMenuProvidedByPlatform, // [intended] only applies to platforms where we supply the context menu. skip: isContextMenuProvidedByPlatform, // [intended] only applies to platforms where we supply the context menu.
); );
testWidgets('Share shows up on iOS only', (WidgetTester tester) async { testWidgetsWithLeakTracking('Share shows up on iOS only', (WidgetTester tester) async {
String? lastShare; String? lastShare;
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
.setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async { .setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async {
...@@ -362,6 +367,7 @@ void main() { ...@@ -362,6 +367,7 @@ void main() {
final TextEditingController controller = TextEditingController( final TextEditingController controller = TextEditingController(
text: 'Test', text: 'Test',
); );
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
home: Center( home: Center(
...@@ -397,10 +403,11 @@ void main() { ...@@ -397,10 +403,11 @@ void main() {
skip: isContextMenuProvidedByPlatform, // [intended] only applies to platforms where we supply the context menu. skip: isContextMenuProvidedByPlatform, // [intended] only applies to platforms where we supply the context menu.
); );
testWidgets('can use the desktop cut/copy/paste buttons on Mac', (WidgetTester tester) async { testWidgetsWithLeakTracking('can use the desktop cut/copy/paste buttons on Mac', (WidgetTester tester) async {
final TextEditingController controller = TextEditingController( final TextEditingController controller = TextEditingController(
text: 'blah1 blah2', text: 'blah1 blah2',
); );
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
home: Center( home: Center(
...@@ -472,11 +479,13 @@ void main() { ...@@ -472,11 +479,13 @@ void main() {
skip: kIsWeb, // [intended] the web handles this on its own. skip: kIsWeb, // [intended] the web handles this on its own.
); );
testWidgets('can get text selection color initially on desktop', (WidgetTester tester) async { testWidgetsWithLeakTracking('can get text selection color initially on desktop', (WidgetTester tester) async {
final FocusNode focusNode = FocusNode(); final FocusNode focusNode = FocusNode();
addTearDown(focusNode.dispose);
final TextEditingController controller = TextEditingController( final TextEditingController controller = TextEditingController(
text: 'blah1 blah2', text: 'blah1 blah2',
); );
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
home: Center( home: Center(
...@@ -502,10 +511,11 @@ void main() { ...@@ -502,10 +511,11 @@ void main() {
); );
}); });
testWidgets('Activates the text field when receives semantics focus on Mac, Windows', (WidgetTester tester) async { testWidgetsWithLeakTracking('Activates the text field when receives semantics focus on Mac, Windows', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester); final SemanticsTester semantics = SemanticsTester(tester);
final SemanticsOwner semanticsOwner = tester.binding.pipelineOwner.semanticsOwner!; final SemanticsOwner semanticsOwner = tester.binding.pipelineOwner.semanticsOwner!;
final FocusNode focusNode = FocusNode(); final FocusNode focusNode = FocusNode();
addTearDown(focusNode.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
home: CupertinoTextField(focusNode: focusNode), home: CupertinoTextField(focusNode: focusNode),
...@@ -552,7 +562,7 @@ void main() { ...@@ -552,7 +562,7 @@ void main() {
semantics.dispose(); semantics.dispose();
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.macOS, TargetPlatform.windows })); }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.macOS, TargetPlatform.windows }));
testWidgets( testWidgetsWithLeakTracking(
'takes available space horizontally and takes intrinsic space vertically no-strut', 'takes available space horizontally and takes intrinsic space vertically no-strut',
(WidgetTester tester) async { (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
...@@ -573,7 +583,7 @@ void main() { ...@@ -573,7 +583,7 @@ void main() {
}, },
); );
testWidgets('sets cursorOpacityAnimates on EditableText correctly', (WidgetTester tester) async { testWidgetsWithLeakTracking('sets cursorOpacityAnimates on EditableText correctly', (WidgetTester tester) async {
// True // True
...@@ -598,7 +608,7 @@ void main() { ...@@ -598,7 +608,7 @@ void main() {
expect(editableText.cursorOpacityAnimates, false); expect(editableText.cursorOpacityAnimates, false);
}); });
testWidgets( testWidgetsWithLeakTracking(
'takes available space horizontally and takes intrinsic space vertically', 'takes available space horizontally and takes intrinsic space vertically',
(WidgetTester tester) async { (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
...@@ -619,7 +629,7 @@ void main() { ...@@ -619,7 +629,7 @@ void main() {
}, },
); );
testWidgets( testWidgetsWithLeakTracking(
'uses DefaultSelectionStyle for selection and cursor colors if provided', 'uses DefaultSelectionStyle for selection and cursor colors if provided',
(WidgetTester tester) async { (WidgetTester tester) async {
const Color selectionColor = Colors.black; const Color selectionColor = Colors.black;
...@@ -645,11 +655,12 @@ void main() { ...@@ -645,11 +655,12 @@ void main() {
}, },
); );
testWidgets('Text field drops selection color when losing focus', (WidgetTester tester) async { testWidgetsWithLeakTracking('Text field drops selection color when losing focus', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/103341. // Regression test for https://github.com/flutter/flutter/issues/103341.
final Key key1 = UniqueKey(); final Key key1 = UniqueKey();
final Key key2 = UniqueKey(); final Key key2 = UniqueKey();
final TextEditingController controller1 = TextEditingController(); final TextEditingController controller1 = TextEditingController();
addTearDown(controller1.dispose);
const Color selectionColor = Colors.orange; const Color selectionColor = Colors.orange;
const Color cursorColor = Colors.red; const Color cursorColor = Colors.red;
...@@ -702,7 +713,7 @@ void main() { ...@@ -702,7 +713,7 @@ void main() {
expect(state2.widget.selectionColor, selectionColor); expect(state2.widget.selectionColor, selectionColor);
}); });
testWidgets( testWidgetsWithLeakTracking(
'multi-lined text fields are intrinsically taller no-strut', 'multi-lined text fields are intrinsically taller no-strut',
(WidgetTester tester) async { (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
...@@ -726,7 +737,7 @@ void main() { ...@@ -726,7 +737,7 @@ void main() {
}, },
); );
testWidgets( testWidgetsWithLeakTracking(
'multi-lined text fields are intrinsically taller', 'multi-lined text fields are intrinsically taller',
(WidgetTester tester) async { (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
...@@ -747,7 +758,7 @@ void main() { ...@@ -747,7 +758,7 @@ void main() {
}, },
); );
testWidgets( testWidgetsWithLeakTracking(
'strut height override', 'strut height override',
(WidgetTester tester) async { (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
...@@ -776,7 +787,7 @@ void main() { ...@@ -776,7 +787,7 @@ void main() {
skip: isBrowser, // https://github.com/flutter/flutter/issues/32243 skip: isBrowser, // https://github.com/flutter/flutter/issues/32243
); );
testWidgets( testWidgetsWithLeakTracking(
'strut forces field taller', 'strut forces field taller',
(WidgetTester tester) async { (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
...@@ -806,7 +817,7 @@ void main() { ...@@ -806,7 +817,7 @@ void main() {
skip: isBrowser, // https://github.com/flutter/flutter/issues/32243 skip: isBrowser, // https://github.com/flutter/flutter/issues/32243
); );
testWidgets( testWidgetsWithLeakTracking(
'default text field has a border', 'default text field has a border',
(WidgetTester tester) async { (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
...@@ -861,7 +872,7 @@ void main() { ...@@ -861,7 +872,7 @@ void main() {
}, },
); );
testWidgets( testWidgetsWithLeakTracking(
'decoration can be overridden', 'decoration can be overridden',
(WidgetTester tester) async { (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
...@@ -884,14 +895,16 @@ void main() { ...@@ -884,14 +895,16 @@ void main() {
}, },
); );
testWidgets( testWidgetsWithLeakTracking(
'text entries are padded by default', 'text entries are padded by default',
(WidgetTester tester) async { (WidgetTester tester) async {
final TextEditingController controller = TextEditingController(text: 'initial');
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
home: Center( home: Center(
child: CupertinoTextField( child: CupertinoTextField(
controller: TextEditingController(text: 'initial'), controller: controller,
), ),
), ),
), ),
...@@ -904,7 +917,7 @@ void main() { ...@@ -904,7 +917,7 @@ void main() {
}, },
); );
testWidgets('iOS cursor has offset', (WidgetTester tester) async { testWidgetsWithLeakTracking('iOS cursor has offset', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
const CupertinoApp( const CupertinoApp(
home: CupertinoTextField(), home: CupertinoTextField(),
...@@ -915,7 +928,7 @@ void main() { ...@@ -915,7 +928,7 @@ void main() {
expect(editableText.cursorOffset, const Offset(-2.0 / 3.0, 0)); expect(editableText.cursorOffset, const Offset(-2.0 / 3.0, 0));
}); });
testWidgets('Cursor radius is 2.0', (WidgetTester tester) async { testWidgetsWithLeakTracking('Cursor radius is 2.0', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
const CupertinoApp( const CupertinoApp(
home: CupertinoTextField(), home: CupertinoTextField(),
...@@ -928,7 +941,7 @@ void main() { ...@@ -928,7 +941,7 @@ void main() {
expect(renderEditable.cursorRadius, const Radius.circular(2.0)); expect(renderEditable.cursorRadius, const Radius.circular(2.0));
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS })); }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
testWidgets('Cupertino cursor android golden', (WidgetTester tester) async { testWidgetsWithLeakTracking('Cupertino cursor android golden', (WidgetTester tester) async {
final Widget widget = CupertinoApp( final Widget widget = CupertinoApp(
home: Center( home: Center(
child: RepaintBoundary( child: RepaintBoundary(
...@@ -955,7 +968,7 @@ void main() { ...@@ -955,7 +968,7 @@ void main() {
); );
}); });
testWidgets('Cupertino cursor golden', (WidgetTester tester) async { testWidgetsWithLeakTracking('Cupertino cursor golden', (WidgetTester tester) async {
final Widget widget = CupertinoApp( final Widget widget = CupertinoApp(
home: Center( home: Center(
child: RepaintBoundary( child: RepaintBoundary(
...@@ -984,10 +997,11 @@ void main() { ...@@ -984,10 +997,11 @@ void main() {
); );
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS })); }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
testWidgets( testWidgetsWithLeakTracking(
'can control text content via controller', 'can control text content via controller',
(WidgetTester tester) async { (WidgetTester tester) async {
final TextEditingController controller = TextEditingController(); final TextEditingController controller = TextEditingController();
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
...@@ -1011,7 +1025,7 @@ void main() { ...@@ -1011,7 +1025,7 @@ void main() {
}, },
); );
testWidgets( testWidgetsWithLeakTracking(
'placeholder respects textAlign', 'placeholder respects textAlign',
(WidgetTester tester) async { (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
...@@ -1036,7 +1050,7 @@ void main() { ...@@ -1036,7 +1050,7 @@ void main() {
}, },
); );
testWidgets('placeholder dark mode', (WidgetTester tester) async { testWidgetsWithLeakTracking('placeholder dark mode', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
const CupertinoApp( const CupertinoApp(
theme: CupertinoThemeData(brightness: Brightness.dark), theme: CupertinoThemeData(brightness: Brightness.dark),
...@@ -1053,7 +1067,7 @@ void main() { ...@@ -1053,7 +1067,7 @@ void main() {
expect(placeholder.style!.color!.value, CupertinoColors.placeholderText.darkColor.value); expect(placeholder.style!.color!.value, CupertinoColors.placeholderText.darkColor.value);
}); });
testWidgets( testWidgetsWithLeakTracking(
'placeholders are lightly colored and disappears once typing starts', 'placeholders are lightly colored and disappears once typing starts',
(WidgetTester tester) async { (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
...@@ -1076,7 +1090,7 @@ void main() { ...@@ -1076,7 +1090,7 @@ void main() {
}, },
); );
testWidgets( testWidgetsWithLeakTracking(
"placeholderStyle modifies placeholder's style and doesn't affect text's style", "placeholderStyle modifies placeholder's style and doesn't affect text's style",
(WidgetTester tester) async { (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
...@@ -1110,17 +1124,20 @@ void main() { ...@@ -1110,17 +1124,20 @@ void main() {
}, },
); );
testWidgets( testWidgetsWithLeakTracking(
'prefix widget is in front of the text', 'prefix widget is in front of the text',
(WidgetTester tester) async { (WidgetTester tester) async {
final FocusNode focusNode = FocusNode(); final FocusNode focusNode = FocusNode();
addTearDown(focusNode.dispose);
final TextEditingController controller = TextEditingController(text: 'input');
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
home: Center( home: Center(
child: CupertinoTextField( child: CupertinoTextField(
focusNode: focusNode, focusNode: focusNode,
prefix: const Icon(CupertinoIcons.add), prefix: const Icon(CupertinoIcons.add),
controller: TextEditingController(text: 'input'), controller: controller,
), ),
), ),
), ),
...@@ -1140,7 +1157,7 @@ void main() { ...@@ -1140,7 +1157,7 @@ void main() {
}, },
); );
testWidgets( testWidgetsWithLeakTracking(
'prefix widget respects visibility mode', 'prefix widget respects visibility mode',
(WidgetTester tester) async { (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
...@@ -1177,10 +1194,11 @@ void main() { ...@@ -1177,10 +1194,11 @@ void main() {
}, },
); );
testWidgets( testWidgetsWithLeakTracking(
'suffix widget is after the text', 'suffix widget is after the text',
(WidgetTester tester) async { (WidgetTester tester) async {
final FocusNode focusNode = FocusNode(); final FocusNode focusNode = FocusNode();
addTearDown(focusNode.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
home: Center( home: Center(
...@@ -1206,7 +1224,7 @@ void main() { ...@@ -1206,7 +1224,7 @@ void main() {
}, },
); );
testWidgets( testWidgetsWithLeakTracking(
'suffix widget respects visibility mode', 'suffix widget respects visibility mode',
(WidgetTester tester) async { (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
...@@ -1230,7 +1248,7 @@ void main() { ...@@ -1230,7 +1248,7 @@ void main() {
}, },
); );
testWidgets( testWidgetsWithLeakTracking(
'can customize padding', 'can customize padding',
(WidgetTester tester) async { (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
...@@ -1250,7 +1268,7 @@ void main() { ...@@ -1250,7 +1268,7 @@ void main() {
}, },
); );
testWidgets( testWidgetsWithLeakTracking(
'padding is in between prefix and suffix no-strut', 'padding is in between prefix and suffix no-strut',
(WidgetTester tester) async { (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
...@@ -1308,7 +1326,7 @@ void main() { ...@@ -1308,7 +1326,7 @@ void main() {
}, },
); );
testWidgets( testWidgetsWithLeakTracking(
'padding is in between prefix and suffix', 'padding is in between prefix and suffix',
(WidgetTester tester) async { (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
...@@ -1364,10 +1382,11 @@ void main() { ...@@ -1364,10 +1382,11 @@ void main() {
}, },
); );
testWidgets( testWidgetsWithLeakTracking(
'clear button shows with right visibility mode', 'clear button shows with right visibility mode',
(WidgetTester tester) async { (WidgetTester tester) async {
final TextEditingController controller = TextEditingController(); final TextEditingController controller = TextEditingController();
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
home: Center( home: Center(
...@@ -1435,10 +1454,11 @@ void main() { ...@@ -1435,10 +1454,11 @@ void main() {
}, },
); );
testWidgets( testWidgetsWithLeakTracking(
'clear button removes text', 'clear button removes text',
(WidgetTester tester) async { (WidgetTester tester) async {
final TextEditingController controller = TextEditingController(); final TextEditingController controller = TextEditingController();
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
home: Center( home: Center(
...@@ -1464,11 +1484,12 @@ void main() { ...@@ -1464,11 +1484,12 @@ void main() {
}, },
); );
testWidgets( testWidgetsWithLeakTracking(
'tapping clear button also calls onChanged when text not empty', 'tapping clear button also calls onChanged when text not empty',
(WidgetTester tester) async { (WidgetTester tester) async {
String value = 'text entry'; String value = 'text entry';
final TextEditingController controller = TextEditingController(); final TextEditingController controller = TextEditingController();
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
home: Center( home: Center(
...@@ -1494,10 +1515,11 @@ void main() { ...@@ -1494,10 +1515,11 @@ void main() {
}, },
); );
testWidgets( testWidgetsWithLeakTracking(
'clear button yields precedence to suffix', 'clear button yields precedence to suffix',
(WidgetTester tester) async { (WidgetTester tester) async {
final TextEditingController controller = TextEditingController(); final TextEditingController controller = TextEditingController();
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
home: Center( home: Center(
...@@ -1533,7 +1555,7 @@ void main() { ...@@ -1533,7 +1555,7 @@ void main() {
}, },
); );
testWidgets( testWidgetsWithLeakTracking(
'font style controls intrinsic height no-strut', 'font style controls intrinsic height no-strut',
(WidgetTester tester) async { (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
...@@ -1572,7 +1594,7 @@ void main() { ...@@ -1572,7 +1594,7 @@ void main() {
}, },
); );
testWidgets( testWidgetsWithLeakTracking(
'font style controls intrinsic height', 'font style controls intrinsic height',
(WidgetTester tester) async { (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
...@@ -1608,7 +1630,7 @@ void main() { ...@@ -1608,7 +1630,7 @@ void main() {
}, },
); );
testWidgets( testWidgetsWithLeakTracking(
'RTL puts attachments to the right places', 'RTL puts attachments to the right places',
(WidgetTester tester) async { (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
...@@ -1638,7 +1660,7 @@ void main() { ...@@ -1638,7 +1660,7 @@ void main() {
}, },
); );
testWidgets( testWidgetsWithLeakTracking(
'text fields with no max lines can grow no-strut', 'text fields with no max lines can grow no-strut',
(WidgetTester tester) async { (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
...@@ -1667,7 +1689,7 @@ void main() { ...@@ -1667,7 +1689,7 @@ void main() {
}, },
); );
testWidgets( testWidgetsWithLeakTracking(
'text fields with no max lines can grow', 'text fields with no max lines can grow',
(WidgetTester tester) async { (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
...@@ -1695,8 +1717,9 @@ void main() { ...@@ -1695,8 +1717,9 @@ void main() {
}, },
); );
testWidgets('cannot enter new lines onto single line TextField', (WidgetTester tester) async { testWidgetsWithLeakTracking('cannot enter new lines onto single line TextField', (WidgetTester tester) async {
final TextEditingController controller = TextEditingController(); final TextEditingController controller = TextEditingController();
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
...@@ -1713,10 +1736,11 @@ void main() { ...@@ -1713,10 +1736,11 @@ void main() {
expect(controller.text, 'abcdef'); expect(controller.text, 'abcdef');
}); });
testWidgets('toolbar colors change with theme brightness, but nothing else', (WidgetTester tester) async { testWidgetsWithLeakTracking('toolbar colors change with theme brightness, but nothing else', (WidgetTester tester) async {
final TextEditingController controller = TextEditingController( final TextEditingController controller = TextEditingController(
text: "j'aime la poutine", text: "j'aime la poutine",
); );
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
...@@ -1775,10 +1799,11 @@ void main() { ...@@ -1775,10 +1799,11 @@ void main() {
expect(text.style!.fontWeight, FontWeight.w400); expect(text.style!.fontWeight, FontWeight.w400);
}, skip: isContextMenuProvidedByPlatform); // [intended] only applies to platforms where we supply the context menu. }, skip: isContextMenuProvidedByPlatform); // [intended] only applies to platforms where we supply the context menu.
testWidgets('text field toolbar options correctly changes options on Apple Platforms', (WidgetTester tester) async { testWidgetsWithLeakTracking('text field toolbar options correctly changes options on Apple Platforms', (WidgetTester tester) async {
final TextEditingController controller = TextEditingController( final TextEditingController controller = TextEditingController(
text: 'Atwater Peel Sherbrooke Bonaventure', text: 'Atwater Peel Sherbrooke Bonaventure',
); );
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
home: Column( home: Column(
...@@ -1825,10 +1850,11 @@ void main() { ...@@ -1825,10 +1850,11 @@ void main() {
skip: isContextMenuProvidedByPlatform, // [intended] only applies to platforms where we supply the context menu. skip: isContextMenuProvidedByPlatform, // [intended] only applies to platforms where we supply the context menu.
); );
testWidgets('text field toolbar options correctly changes options on non-Apple Platforms', (WidgetTester tester) async { testWidgetsWithLeakTracking('text field toolbar options correctly changes options on non-Apple Platforms', (WidgetTester tester) async {
final TextEditingController controller = TextEditingController( final TextEditingController controller = TextEditingController(
text: 'Atwater Peel Sherbrooke Bonaventure', text: 'Atwater Peel Sherbrooke Bonaventure',
); );
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
home: Column( home: Column(
...@@ -1880,8 +1906,9 @@ void main() { ...@@ -1880,8 +1906,9 @@ void main() {
skip: isContextMenuProvidedByPlatform, // [intended] only applies to platforms where we supply the context menu. skip: isContextMenuProvidedByPlatform, // [intended] only applies to platforms where we supply the context menu.
); );
testWidgets('Read only text field', (WidgetTester tester) async { testWidgetsWithLeakTracking('Read only text field', (WidgetTester tester) async {
final TextEditingController controller = TextEditingController(text: 'readonly'); final TextEditingController controller = TextEditingController(text: 'readonly');
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
...@@ -1917,7 +1944,7 @@ void main() { ...@@ -1917,7 +1944,7 @@ void main() {
expect(find.text('Cut'), findsNothing); expect(find.text('Cut'), findsNothing);
}, skip: isContextMenuProvidedByPlatform); // [intended] only applies to platforms where we supply the context menu. }, skip: isContextMenuProvidedByPlatform); // [intended] only applies to platforms where we supply the context menu.
testWidgets('copy paste', (WidgetTester tester) async { testWidgetsWithLeakTracking('copy paste', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
const CupertinoApp( const CupertinoApp(
home: Column( home: Column(
...@@ -1970,12 +1997,13 @@ void main() { ...@@ -1970,12 +1997,13 @@ void main() {
expect(Visibility.of(placeholder2Element), false); expect(Visibility.of(placeholder2Element), false);
}, skip: isContextMenuProvidedByPlatform); // [intended] only applies to platforms where we supply the context menu. }, skip: isContextMenuProvidedByPlatform); // [intended] only applies to platforms where we supply the context menu.
testWidgets( testWidgetsWithLeakTracking(
'tap moves cursor to the edge of the word it tapped on', 'tap moves cursor to the edge of the word it tapped on',
(WidgetTester tester) async { (WidgetTester tester) async {
final TextEditingController controller = TextEditingController( final TextEditingController controller = TextEditingController(
text: 'Atwater Peel Sherbrooke Bonaventure', text: 'Atwater Peel Sherbrooke Bonaventure',
); );
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
home: Center( home: Center(
...@@ -2001,12 +2029,13 @@ void main() { ...@@ -2001,12 +2029,13 @@ void main() {
expect(find.byType(CupertinoButton), findsNothing); expect(find.byType(CupertinoButton), findsNothing);
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS })); }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS }));
testWidgets( testWidgetsWithLeakTracking(
'slow double tap does not trigger double tap', 'slow double tap does not trigger double tap',
(WidgetTester tester) async { (WidgetTester tester) async {
final TextEditingController controller = TextEditingController( final TextEditingController controller = TextEditingController(
text: 'Atwater Peel Sherbrooke Bonaventure', text: 'Atwater Peel Sherbrooke Bonaventure',
); );
addTearDown(controller.dispose);
// On iOS/iPadOS, during a tap we select the edge of the word closest to the tap. // On iOS/iPadOS, during a tap we select the edge of the word closest to the tap.
// On macOS, we select the precise position of the tap. // On macOS, we select the precise position of the tap.
final bool isTargetPlatformIOS = defaultTargetPlatform == TargetPlatform.iOS; final bool isTargetPlatformIOS = defaultTargetPlatform == TargetPlatform.iOS;
...@@ -2035,12 +2064,13 @@ void main() { ...@@ -2035,12 +2064,13 @@ void main() {
expect(find.byType(CupertinoButton), isContextMenuProvidedByPlatform ? findsNothing : isTargetPlatformIOS ? findsNWidgets(2) : findsNothing); expect(find.byType(CupertinoButton), isContextMenuProvidedByPlatform ? findsNothing : isTargetPlatformIOS ? findsNWidgets(2) : findsNothing);
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS })); }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
testWidgets( testWidgetsWithLeakTracking(
'Tapping on a collapsed selection toggles the toolbar', 'Tapping on a collapsed selection toggles the toolbar',
(WidgetTester tester) async { (WidgetTester tester) async {
final TextEditingController controller = TextEditingController( final TextEditingController controller = TextEditingController(
text: 'Atwater Peel Sherbrooke Bonaventure Angrignon Peel Côte-des-Neigse Atwater Peel Sherbrooke Bonaventure Angrignon Peel Côte-des-Neiges', text: 'Atwater Peel Sherbrooke Bonaventure Angrignon Peel Côte-des-Neigse Atwater Peel Sherbrooke Bonaventure Angrignon Peel Côte-des-Neiges',
); );
addTearDown(controller.dispose);
// On iOS/iPadOS, during a tap we select the edge of the word closest to the tap. // On iOS/iPadOS, during a tap we select the edge of the word closest to the tap.
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
...@@ -2120,12 +2150,13 @@ void main() { ...@@ -2120,12 +2150,13 @@ void main() {
variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS }), variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS }),
); );
testWidgets( testWidgetsWithLeakTracking(
'Tapping on a non-collapsed selection toggles the toolbar and retains the selection', 'Tapping on a non-collapsed selection toggles the toolbar and retains the selection',
(WidgetTester tester) async { (WidgetTester tester) async {
final TextEditingController controller = TextEditingController( final TextEditingController controller = TextEditingController(
text: 'Atwater Peel Sherbrooke Bonaventure', text: 'Atwater Peel Sherbrooke Bonaventure',
); );
addTearDown(controller.dispose);
// On iOS/iPadOS, during a tap we select the edge of the word closest to the tap. // On iOS/iPadOS, during a tap we select the edge of the word closest to the tap.
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
...@@ -2194,12 +2225,13 @@ void main() { ...@@ -2194,12 +2225,13 @@ void main() {
variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS }), variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS }),
); );
testWidgets( testWidgetsWithLeakTracking(
'double tap selects word for non-Apple platforms', 'double tap selects word for non-Apple platforms',
(WidgetTester tester) async { (WidgetTester tester) async {
final TextEditingController controller = TextEditingController( final TextEditingController controller = TextEditingController(
text: 'Atwater Peel Sherbrooke Bonaventure', text: 'Atwater Peel Sherbrooke Bonaventure',
); );
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
home: Center( home: Center(
...@@ -2249,12 +2281,13 @@ void main() { ...@@ -2249,12 +2281,13 @@ void main() {
variant: TargetPlatformVariant.all(excluding: <TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS}), variant: TargetPlatformVariant.all(excluding: <TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS}),
); );
testWidgets( testWidgetsWithLeakTracking(
'double tap selects word for Apple platforms', 'double tap selects word for Apple platforms',
(WidgetTester tester) async { (WidgetTester tester) async {
final TextEditingController controller = TextEditingController( final TextEditingController controller = TextEditingController(
text: 'Atwater Peel Sherbrooke Bonaventure', text: 'Atwater Peel Sherbrooke Bonaventure',
); );
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
home: Center( home: Center(
...@@ -2308,12 +2341,13 @@ void main() { ...@@ -2308,12 +2341,13 @@ void main() {
variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }), variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }),
); );
testWidgets( testWidgetsWithLeakTracking(
'double tap does not select word on read-only obscured field', 'double tap does not select word on read-only obscured field',
(WidgetTester tester) async { (WidgetTester tester) async {
final TextEditingController controller = TextEditingController( final TextEditingController controller = TextEditingController(
text: 'Atwater Peel Sherbrooke Bonaventure', text: 'Atwater Peel Sherbrooke Bonaventure',
); );
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
home: Center( home: Center(
...@@ -2346,10 +2380,11 @@ void main() { ...@@ -2346,10 +2380,11 @@ void main() {
}, },
); );
testWidgets( testWidgetsWithLeakTracking(
'Can double click + drag with a mouse to select word by word', 'Can double click + drag with a mouse to select word by word',
(WidgetTester tester) async { (WidgetTester tester) async {
final TextEditingController controller = TextEditingController(); final TextEditingController controller = TextEditingController();
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
...@@ -2395,10 +2430,11 @@ void main() { ...@@ -2395,10 +2430,11 @@ void main() {
}, },
); );
testWidgets( testWidgetsWithLeakTracking(
'Can double tap + drag to select word by word', 'Can double tap + drag to select word by word',
(WidgetTester tester) async { (WidgetTester tester) async {
final TextEditingController controller = TextEditingController(); final TextEditingController controller = TextEditingController();
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
...@@ -2450,9 +2486,14 @@ void main() { ...@@ -2450,9 +2486,14 @@ void main() {
await tester.pump(); await tester.pump();
expect(find.byType(CupertinoButton), isContextMenuProvidedByPlatform ? findsNothing : findsNWidgets(4)); expect(find.byType(CupertinoButton), isContextMenuProvidedByPlatform ? findsNothing : findsNWidgets(4));
}, },
// TODO(derdilla): remove after fixing and leak track other failing tests in
// this file. https://github.com/flutter/flutter/issues/135803
leakTrackingTestConfig: const LeakTrackingTestConfig(notDisposedAllowList:
<String, int?>{'ValueNotifier<_OverlayEntryWidgetState?>': 1})
); );
//
testWidgets('Readonly text field does not have tap action', (WidgetTester tester) async { testWidgetsWithLeakTracking('Readonly text field does not have tap action', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester); final SemanticsTester semantics = SemanticsTester(tester);
await tester.pumpWidget( await tester.pumpWidget(
...@@ -2471,12 +2512,13 @@ void main() { ...@@ -2471,12 +2512,13 @@ void main() {
semantics.dispose(); semantics.dispose();
}); });
testWidgets( testWidgetsWithLeakTracking(
'double tap selects word and first tap of double tap moves cursor', 'double tap selects word and first tap of double tap moves cursor',
(WidgetTester tester) async { (WidgetTester tester) async {
final TextEditingController controller = TextEditingController( final TextEditingController controller = TextEditingController(
text: 'Atwater Peel Sherbrooke Bonaventure', text: 'Atwater Peel Sherbrooke Bonaventure',
); );
addTearDown(controller.dispose);
// On iOS/iPadOS, during a tap we select the edge of the word closest to the tap. // On iOS/iPadOS, during a tap we select the edge of the word closest to the tap.
// On macOS, we select the precise position of the tap. // On macOS, we select the precise position of the tap.
final bool isTargetPlatformIOS = defaultTargetPlatform == TargetPlatform.iOS; final bool isTargetPlatformIOS = defaultTargetPlatform == TargetPlatform.iOS;
...@@ -2516,12 +2558,13 @@ void main() { ...@@ -2516,12 +2558,13 @@ void main() {
expect(find.byType(CupertinoButton), isContextMenuProvidedByPlatform ? findsNothing : (isTargetPlatformIOS ? findsNWidgets(6) : findsNWidgets(3))); expect(find.byType(CupertinoButton), isContextMenuProvidedByPlatform ? findsNothing : (isTargetPlatformIOS ? findsNWidgets(6) : findsNWidgets(3)));
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS })); }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
testWidgets( testWidgetsWithLeakTracking(
'double tap hold selects word', 'double tap hold selects word',
(WidgetTester tester) async { (WidgetTester tester) async {
final TextEditingController controller = TextEditingController( final TextEditingController controller = TextEditingController(
text: 'Atwater Peel Sherbrooke Bonaventure', text: 'Atwater Peel Sherbrooke Bonaventure',
); );
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
home: Center( home: Center(
...@@ -2575,12 +2618,13 @@ void main() { ...@@ -2575,12 +2618,13 @@ void main() {
}, },
); );
testWidgets( testWidgetsWithLeakTracking(
'tap after a double tap select is not affected', 'tap after a double tap select is not affected',
(WidgetTester tester) async { (WidgetTester tester) async {
final TextEditingController controller = TextEditingController( final TextEditingController controller = TextEditingController(
text: 'Atwater Peel Sherbrooke Bonaventure', text: 'Atwater Peel Sherbrooke Bonaventure',
); );
addTearDown(controller.dispose);
// On iOS/iPadOS, during a tap we select the edge of the word closest to the tap. // On iOS/iPadOS, during a tap we select the edge of the word closest to the tap.
// On macOS, we select the precise position of the tap. // On macOS, we select the precise position of the tap.
final bool isTargetPlatformIOS = defaultTargetPlatform == TargetPlatform.iOS; final bool isTargetPlatformIOS = defaultTargetPlatform == TargetPlatform.iOS;
...@@ -2620,10 +2664,11 @@ void main() { ...@@ -2620,10 +2664,11 @@ void main() {
expect(find.byType(CupertinoButton), findsNothing); expect(find.byType(CupertinoButton), findsNothing);
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS })); }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
testWidgets('double tapping a space selects the previous word on iOS', (WidgetTester tester) async { testWidgetsWithLeakTracking('double tapping a space selects the previous word on iOS', (WidgetTester tester) async {
final TextEditingController controller = TextEditingController( final TextEditingController controller = TextEditingController(
text: ' blah blah \n blah', text: ' blah blah \n blah',
); );
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
home: Center( home: Center(
...@@ -2689,10 +2734,11 @@ void main() { ...@@ -2689,10 +2734,11 @@ void main() {
expect(controller.value.selection.extentOffset, 14); expect(controller.value.selection.extentOffset, 14);
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS })); }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS }));
testWidgets('double tapping a space selects the space on Mac', (WidgetTester tester) async { testWidgetsWithLeakTracking('double tapping a space selects the space on Mac', (WidgetTester tester) async {
final TextEditingController controller = TextEditingController( final TextEditingController controller = TextEditingController(
text: ' blah blah', text: ' blah blah',
); );
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
home: Center( home: Center(
...@@ -2743,10 +2789,11 @@ void main() { ...@@ -2743,10 +2789,11 @@ void main() {
expect(controller.value.selection.extentOffset, 1); expect(controller.value.selection.extentOffset, 1);
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.macOS })); }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.macOS }));
testWidgets('double clicking a space selects the space on Mac', (WidgetTester tester) async { testWidgetsWithLeakTracking('double clicking a space selects the space on Mac', (WidgetTester tester) async {
final TextEditingController controller = TextEditingController( final TextEditingController controller = TextEditingController(
text: ' blah blah', text: ' blah blah',
); );
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
home: Center( home: Center(
...@@ -2810,12 +2857,13 @@ void main() { ...@@ -2810,12 +2857,13 @@ void main() {
expect(controller.value.selection.extentOffset, 1); expect(controller.value.selection.extentOffset, 1);
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.macOS })); }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.macOS }));
testWidgets( testWidgetsWithLeakTracking(
'An obscured CupertinoTextField is not selectable when disabled', 'An obscured CupertinoTextField is not selectable when disabled',
(WidgetTester tester) async { (WidgetTester tester) async {
final TextEditingController controller = TextEditingController( final TextEditingController controller = TextEditingController(
text: 'Atwater Peel Sherbrooke Bonaventure', text: 'Atwater Peel Sherbrooke Bonaventure',
); );
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
home: Center( home: Center(
...@@ -2858,12 +2906,13 @@ void main() { ...@@ -2858,12 +2906,13 @@ void main() {
}, },
); );
testWidgets( testWidgetsWithLeakTracking(
'A read-only obscured CupertinoTextField is not selectable', 'A read-only obscured CupertinoTextField is not selectable',
(WidgetTester tester) async { (WidgetTester tester) async {
final TextEditingController controller = TextEditingController( final TextEditingController controller = TextEditingController(
text: 'Atwater Peel Sherbrooke Bonaventure', text: 'Atwater Peel Sherbrooke Bonaventure',
); );
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
home: Center( home: Center(
...@@ -2906,12 +2955,13 @@ void main() { ...@@ -2906,12 +2955,13 @@ void main() {
}, },
); );
testWidgets( testWidgetsWithLeakTracking(
'An obscured CupertinoTextField is selectable by default', 'An obscured CupertinoTextField is selectable by default',
(WidgetTester tester) async { (WidgetTester tester) async {
final TextEditingController controller = TextEditingController( final TextEditingController controller = TextEditingController(
text: 'Atwater Peel Sherbrooke Bonaventure', text: 'Atwater Peel Sherbrooke Bonaventure',
); );
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
home: Center( home: Center(
...@@ -2953,10 +3003,11 @@ void main() { ...@@ -2953,10 +3003,11 @@ void main() {
}, },
); );
testWidgets('An obscured TextField has correct default context menu', (WidgetTester tester) async { testWidgetsWithLeakTracking('An obscured TextField has correct default context menu', (WidgetTester tester) async {
final TextEditingController controller = TextEditingController( final TextEditingController controller = TextEditingController(
text: 'Atwater Peel Sherbrooke Bonaventure', text: 'Atwater Peel Sherbrooke Bonaventure',
); );
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
...@@ -2997,12 +3048,13 @@ void main() { ...@@ -2997,12 +3048,13 @@ void main() {
expect(find.text('Cut'), findsNothing); expect(find.text('Cut'), findsNothing);
}, skip: isContextMenuProvidedByPlatform); // [intended] only applies to platforms where we supply the context menu. }, skip: isContextMenuProvidedByPlatform); // [intended] only applies to platforms where we supply the context menu.
testWidgets( testWidgetsWithLeakTracking(
'long press selects the word at the long press position and shows toolbar on non-Apple platforms', 'long press selects the word at the long press position and shows toolbar on non-Apple platforms',
(WidgetTester tester) async { (WidgetTester tester) async {
final TextEditingController controller = TextEditingController( final TextEditingController controller = TextEditingController(
text: 'Atwater Peel Sherbrooke Bonaventure', text: 'Atwater Peel Sherbrooke Bonaventure',
); );
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
home: Center( home: Center(
...@@ -3030,12 +3082,13 @@ void main() { ...@@ -3030,12 +3082,13 @@ void main() {
variant: TargetPlatformVariant.all(excluding: <TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }), variant: TargetPlatformVariant.all(excluding: <TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }),
); );
testWidgets( testWidgetsWithLeakTracking(
'long press moves cursor to the exact long press position and shows toolbar on Apple platforms', 'long press moves cursor to the exact long press position and shows toolbar on Apple platforms',
(WidgetTester tester) async { (WidgetTester tester) async {
final TextEditingController controller = TextEditingController( final TextEditingController controller = TextEditingController(
text: 'Atwater Peel Sherbrooke Bonaventure', text: 'Atwater Peel Sherbrooke Bonaventure',
); );
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
home: Center( home: Center(
...@@ -3074,12 +3127,13 @@ void main() { ...@@ -3074,12 +3127,13 @@ void main() {
variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }), variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }),
); );
testWidgets( testWidgetsWithLeakTracking(
'long press tap cannot initiate a double tap', 'long press tap cannot initiate a double tap',
(WidgetTester tester) async { (WidgetTester tester) async {
final TextEditingController controller = TextEditingController( final TextEditingController controller = TextEditingController(
text: 'Atwater Peel Sherbrooke Bonaventure', text: 'Atwater Peel Sherbrooke Bonaventure',
); );
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
home: Center( home: Center(
...@@ -3124,12 +3178,13 @@ void main() { ...@@ -3124,12 +3178,13 @@ void main() {
expect(find.byType(CupertinoButton), findsNothing); expect(find.byType(CupertinoButton), findsNothing);
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS })); }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
testWidgets( testWidgetsWithLeakTracking(
'long press drag selects word by word and shows toolbar on lift on non-Apple platforms', 'long press drag selects word by word and shows toolbar on lift on non-Apple platforms',
(WidgetTester tester) async { (WidgetTester tester) async {
final TextEditingController controller = TextEditingController( final TextEditingController controller = TextEditingController(
text: 'Atwater Peel Sherbrooke Bonaventure', text: 'Atwater Peel Sherbrooke Bonaventure',
); );
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
home: Center( home: Center(
...@@ -3188,12 +3243,13 @@ void main() { ...@@ -3188,12 +3243,13 @@ void main() {
variant: TargetPlatformVariant.all(excluding: <TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }), variant: TargetPlatformVariant.all(excluding: <TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }),
); );
testWidgets( testWidgetsWithLeakTracking(
'long press drag on a focused TextField moves the cursor under the drag and shows toolbar on lift on Apple platforms', 'long press drag on a focused TextField moves the cursor under the drag and shows toolbar on lift on Apple platforms',
(WidgetTester tester) async { (WidgetTester tester) async {
final TextEditingController controller = TextEditingController( final TextEditingController controller = TextEditingController(
text: 'Atwater Peel Sherbrooke Bonaventure', text: 'Atwater Peel Sherbrooke Bonaventure',
); );
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
home: Center( home: Center(
...@@ -3263,10 +3319,11 @@ void main() { ...@@ -3263,10 +3319,11 @@ void main() {
variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }), variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }),
); );
testWidgets('long press drag can edge scroll on non-Apple platforms', (WidgetTester tester) async { testWidgetsWithLeakTracking('long press drag can edge scroll on non-Apple platforms', (WidgetTester tester) async {
final TextEditingController controller = TextEditingController( final TextEditingController controller = TextEditingController(
text: 'Atwater Peel Sherbrooke Bonaventure Angrignon Peel Côte-des-Neiges', text: 'Atwater Peel Sherbrooke Bonaventure Angrignon Peel Côte-des-Neiges',
); );
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
home: Center( home: Center(
...@@ -3349,10 +3406,11 @@ void main() { ...@@ -3349,10 +3406,11 @@ void main() {
expect(firstCharEndpoint[0].point.dx, moreOrLessEquals(-310.30, epsilon: 1)); expect(firstCharEndpoint[0].point.dx, moreOrLessEquals(-310.30, epsilon: 1));
}, variant: TargetPlatformVariant.all(excluding: <TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS })); }, variant: TargetPlatformVariant.all(excluding: <TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
testWidgets('long press drag can edge scroll on Apple platforms', (WidgetTester tester) async { testWidgetsWithLeakTracking('long press drag can edge scroll on Apple platforms', (WidgetTester tester) async {
final TextEditingController controller = TextEditingController( final TextEditingController controller = TextEditingController(
text: 'Atwater Peel Sherbrooke Bonaventure Angrignon Peel Côte-des-Neiges', text: 'Atwater Peel Sherbrooke Bonaventure Angrignon Peel Côte-des-Neiges',
); );
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
home: Center( home: Center(
...@@ -3450,12 +3508,13 @@ void main() { ...@@ -3450,12 +3508,13 @@ void main() {
expect(firstCharEndpoint[0].point.dx, moreOrLessEquals(-310.20, epsilon: 0.25)); expect(firstCharEndpoint[0].point.dx, moreOrLessEquals(-310.20, epsilon: 0.25));
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS })); }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
testWidgets( testWidgetsWithLeakTracking(
'long tap after a double tap select is not affected', 'long tap after a double tap select is not affected',
(WidgetTester tester) async { (WidgetTester tester) async {
final TextEditingController controller = TextEditingController( final TextEditingController controller = TextEditingController(
text: 'Atwater Peel Sherbrooke Bonaventure', text: 'Atwater Peel Sherbrooke Bonaventure',
); );
addTearDown(controller.dispose);
// On iOS/iPadOS, during a tap we select the edge of the word closest to the tap. // On iOS/iPadOS, during a tap we select the edge of the word closest to the tap.
// On macOS, we select the precise position of the tap. // On macOS, we select the precise position of the tap.
final bool isTargetPlatformIOS = defaultTargetPlatform == TargetPlatform.iOS; final bool isTargetPlatformIOS = defaultTargetPlatform == TargetPlatform.iOS;
...@@ -3502,12 +3561,13 @@ void main() { ...@@ -3502,12 +3561,13 @@ void main() {
expect(find.byType(CupertinoButton), findsNWidgets(toolbarButtons)); expect(find.byType(CupertinoButton), findsNWidgets(toolbarButtons));
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS })); }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
testWidgets( testWidgetsWithLeakTracking(
'double tap after a long tap is not affected', 'double tap after a long tap is not affected',
(WidgetTester tester) async { (WidgetTester tester) async {
final TextEditingController controller = TextEditingController( final TextEditingController controller = TextEditingController(
text: 'Atwater Peel Sherbrooke Bonaventure', text: 'Atwater Peel Sherbrooke Bonaventure',
); );
addTearDown(controller.dispose);
// On iOS/iPadOS, during a tap we select the edge of the word closest to the tap. // On iOS/iPadOS, during a tap we select the edge of the word closest to the tap.
// On macOS, we select the precise position of the tap. // On macOS, we select the precise position of the tap.
final bool isTargetPlatformIOS = defaultTargetPlatform == TargetPlatform.iOS; final bool isTargetPlatformIOS = defaultTargetPlatform == TargetPlatform.iOS;
...@@ -3561,12 +3621,13 @@ void main() { ...@@ -3561,12 +3621,13 @@ void main() {
expect(find.byType(CupertinoButton), isContextMenuProvidedByPlatform ? findsNothing : (isTargetPlatformIOS ? findsNWidgets(6) : findsNWidgets(3))); expect(find.byType(CupertinoButton), isContextMenuProvidedByPlatform ? findsNothing : (isTargetPlatformIOS ? findsNWidgets(6) : findsNWidgets(3)));
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS })); }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
testWidgets( testWidgetsWithLeakTracking(
'double tap chains work', 'double tap chains work',
(WidgetTester tester) async { (WidgetTester tester) async {
final TextEditingController controller = TextEditingController( final TextEditingController controller = TextEditingController(
text: 'Atwater Peel Sherbrooke Bonaventure', text: 'Atwater Peel Sherbrooke Bonaventure',
); );
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
home: Center( home: Center(
...@@ -3640,11 +3701,12 @@ void main() { ...@@ -3640,11 +3701,12 @@ void main() {
'all good people\n' // 22 + 16 => 38 'all good people\n' // 22 + 16 => 38
'to come to the aid\n' // 38 + 19 => 57 'to come to the aid\n' // 38 + 19 => 57
'of their country.'; // 57 + 17 => 74 'of their country.'; // 57 + 17 => 74
testWidgets( testWidgetsWithLeakTracking(
'Can triple tap to select a paragraph on mobile platforms when tapping at a word edge', 'Can triple tap to select a paragraph on mobile platforms when tapping at a word edge',
(WidgetTester tester) async { (WidgetTester tester) async {
// TODO(Renzo-Olivares): Enable, currently broken because selection overlay blocks the TextSelectionGestureDetector. // TODO(Renzo-Olivares): Enable, currently broken because selection overlay blocks the TextSelectionGestureDetector.
final TextEditingController controller = TextEditingController(); final TextEditingController controller = TextEditingController();
addTearDown(controller.dispose);
final bool isTargetPlatformApple = defaultTargetPlatform == TargetPlatform.iOS; final bool isTargetPlatformApple = defaultTargetPlatform == TargetPlatform.iOS;
await tester.pumpWidget( await tester.pumpWidget(
...@@ -3700,10 +3762,11 @@ void main() { ...@@ -3700,10 +3762,11 @@ void main() {
skip: true, // https://github.com/flutter/flutter/issues/123415 skip: true, // https://github.com/flutter/flutter/issues/123415
); );
testWidgets( testWidgetsWithLeakTracking(
'Can triple tap to select a paragraph on mobile platforms', 'Can triple tap to select a paragraph on mobile platforms',
(WidgetTester tester) async { (WidgetTester tester) async {
final TextEditingController controller = TextEditingController(); final TextEditingController controller = TextEditingController();
addTearDown(controller.dispose);
final bool isTargetPlatformApple = defaultTargetPlatform == TargetPlatform.iOS; final bool isTargetPlatformApple = defaultTargetPlatform == TargetPlatform.iOS;
await tester.pumpWidget( await tester.pumpWidget(
...@@ -3758,11 +3821,12 @@ void main() { ...@@ -3758,11 +3821,12 @@ void main() {
variant: TargetPlatformVariant.mobile(), variant: TargetPlatformVariant.mobile(),
); );
testWidgets( testWidgetsWithLeakTracking(
'Triple click at the beginning of a line should not select the previous paragraph', 'Triple click at the beginning of a line should not select the previous paragraph',
(WidgetTester tester) async { (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/132126 // Regression test for https://github.com/flutter/flutter/issues/132126
final TextEditingController controller = TextEditingController(); final TextEditingController controller = TextEditingController();
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
...@@ -3815,11 +3879,12 @@ void main() { ...@@ -3815,11 +3879,12 @@ void main() {
variant: TargetPlatformVariant.all(excluding: <TargetPlatform>{ TargetPlatform.linux }), variant: TargetPlatformVariant.all(excluding: <TargetPlatform>{ TargetPlatform.linux }),
); );
testWidgets( testWidgetsWithLeakTracking(
'Triple click at the end of text should select the previous paragraph', 'Triple click at the end of text should select the previous paragraph',
(WidgetTester tester) async { (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/132126. // Regression test for https://github.com/flutter/flutter/issues/132126.
final TextEditingController controller = TextEditingController(); final TextEditingController controller = TextEditingController();
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
...@@ -3873,12 +3938,13 @@ void main() { ...@@ -3873,12 +3938,13 @@ void main() {
variant: TargetPlatformVariant.all(excluding: <TargetPlatform>{ TargetPlatform.linux }), variant: TargetPlatformVariant.all(excluding: <TargetPlatform>{ TargetPlatform.linux }),
); );
testWidgets( testWidgetsWithLeakTracking(
'triple tap chains work on Non-Apple mobile platforms', 'triple tap chains work on Non-Apple mobile platforms',
(WidgetTester tester) async { (WidgetTester tester) async {
final TextEditingController controller = TextEditingController( final TextEditingController controller = TextEditingController(
text: 'Atwater Peel Sherbrooke Bonaventure', text: 'Atwater Peel Sherbrooke Bonaventure',
); );
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
home: Center( home: Center(
...@@ -3963,12 +4029,13 @@ void main() { ...@@ -3963,12 +4029,13 @@ void main() {
variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android, TargetPlatform.fuchsia }), variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android, TargetPlatform.fuchsia }),
); );
testWidgets( testWidgetsWithLeakTracking(
'triple tap chains work on Apple platforms', 'triple tap chains work on Apple platforms',
(WidgetTester tester) async { (WidgetTester tester) async {
final TextEditingController controller = TextEditingController( final TextEditingController controller = TextEditingController(
text: 'Atwater Peel Sherbrooke Bonaventure\nThe fox jumped over the fence.', text: 'Atwater Peel Sherbrooke Bonaventure\nThe fox jumped over the fence.',
); );
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
home: Center( home: Center(
...@@ -4063,12 +4130,13 @@ void main() { ...@@ -4063,12 +4130,13 @@ void main() {
variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS }), variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS }),
); );
testWidgets( testWidgetsWithLeakTracking(
'triple click chains work', 'triple click chains work',
(WidgetTester tester) async { (WidgetTester tester) async {
final TextEditingController controller = TextEditingController( final TextEditingController controller = TextEditingController(
text: testValueA, text: testValueA,
); );
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
home: Center( home: Center(
...@@ -4180,12 +4248,13 @@ void main() { ...@@ -4180,12 +4248,13 @@ void main() {
variant: TargetPlatformVariant.desktop(), variant: TargetPlatformVariant.desktop(),
); );
testWidgets( testWidgetsWithLeakTracking(
'triple click after a click on desktop platforms', 'triple click after a click on desktop platforms',
(WidgetTester tester) async { (WidgetTester tester) async {
final TextEditingController controller = TextEditingController( final TextEditingController controller = TextEditingController(
text: testValueA, text: testValueA,
); );
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
home: Center( home: Center(
...@@ -4244,12 +4313,13 @@ void main() { ...@@ -4244,12 +4313,13 @@ void main() {
variant: TargetPlatformVariant.desktop(), variant: TargetPlatformVariant.desktop(),
); );
testWidgets( testWidgetsWithLeakTracking(
'Can triple tap to select all on a single-line textfield on mobile platforms', 'Can triple tap to select all on a single-line textfield on mobile platforms',
(WidgetTester tester) async { (WidgetTester tester) async {
final TextEditingController controller = TextEditingController( final TextEditingController controller = TextEditingController(
text: testValueB, text: testValueB,
); );
addTearDown(controller.dispose);
final bool isTargetPlatformApple = defaultTargetPlatform == TargetPlatform.iOS; final bool isTargetPlatformApple = defaultTargetPlatform == TargetPlatform.iOS;
await tester.pumpWidget( await tester.pumpWidget(
...@@ -4299,12 +4369,13 @@ void main() { ...@@ -4299,12 +4369,13 @@ void main() {
variant: TargetPlatformVariant.mobile(), variant: TargetPlatformVariant.mobile(),
); );
testWidgets( testWidgetsWithLeakTracking(
'Can triple click to select all on a single-line textfield on desktop platforms', 'Can triple click to select all on a single-line textfield on desktop platforms',
(WidgetTester tester) async { (WidgetTester tester) async {
final TextEditingController controller = TextEditingController( final TextEditingController controller = TextEditingController(
text: testValueA, text: testValueA,
); );
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
...@@ -4355,10 +4426,11 @@ void main() { ...@@ -4355,10 +4426,11 @@ void main() {
variant: TargetPlatformVariant.desktop(), variant: TargetPlatformVariant.desktop(),
); );
testWidgets( testWidgetsWithLeakTracking(
'Can triple click to select a line on Linux', 'Can triple click to select a line on Linux',
(WidgetTester tester) async { (WidgetTester tester) async {
final TextEditingController controller = TextEditingController(); final TextEditingController controller = TextEditingController();
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
...@@ -4416,10 +4488,11 @@ void main() { ...@@ -4416,10 +4488,11 @@ void main() {
variant: TargetPlatformVariant.only(TargetPlatform.linux), variant: TargetPlatformVariant.only(TargetPlatform.linux),
); );
testWidgets( testWidgetsWithLeakTracking(
'Can triple click to select a paragraph', 'Can triple click to select a paragraph',
(WidgetTester tester) async { (WidgetTester tester) async {
final TextEditingController controller = TextEditingController(); final TextEditingController controller = TextEditingController();
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
...@@ -4477,10 +4550,11 @@ void main() { ...@@ -4477,10 +4550,11 @@ void main() {
variant: TargetPlatformVariant.all(excluding: <TargetPlatform>{ TargetPlatform.linux }), variant: TargetPlatformVariant.all(excluding: <TargetPlatform>{ TargetPlatform.linux }),
); );
testWidgets( testWidgetsWithLeakTracking(
'Can triple click + drag to select line by line on Linux', 'Can triple click + drag to select line by line on Linux',
(WidgetTester tester) async { (WidgetTester tester) async {
final TextEditingController controller = TextEditingController(); final TextEditingController controller = TextEditingController();
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
...@@ -4579,10 +4653,11 @@ void main() { ...@@ -4579,10 +4653,11 @@ void main() {
variant: TargetPlatformVariant.only(TargetPlatform.linux), variant: TargetPlatformVariant.only(TargetPlatform.linux),
); );
testWidgets( testWidgetsWithLeakTracking(
'Can triple click + drag to select paragraph by paragraph', 'Can triple click + drag to select paragraph by paragraph',
(WidgetTester tester) async { (WidgetTester tester) async {
final TextEditingController controller = TextEditingController(); final TextEditingController controller = TextEditingController();
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
...@@ -4681,12 +4756,13 @@ void main() { ...@@ -4681,12 +4756,13 @@ void main() {
variant: TargetPlatformVariant.all(excluding: <TargetPlatform>{ TargetPlatform.linux }), variant: TargetPlatformVariant.all(excluding: <TargetPlatform>{ TargetPlatform.linux }),
); );
testWidgets( testWidgetsWithLeakTracking(
'Going past triple click retains the selection on Apple platforms', 'Going past triple click retains the selection on Apple platforms',
(WidgetTester tester) async { (WidgetTester tester) async {
final TextEditingController controller = TextEditingController( final TextEditingController controller = TextEditingController(
text: testValueA, text: testValueA,
); );
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
home: Center( home: Center(
...@@ -4768,12 +4844,13 @@ void main() { ...@@ -4768,12 +4844,13 @@ void main() {
variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }), variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }),
); );
testWidgets( testWidgetsWithLeakTracking(
'Tap count resets when going past a triple tap on Android, Fuchsia, and Linux', 'Tap count resets when going past a triple tap on Android, Fuchsia, and Linux',
(WidgetTester tester) async { (WidgetTester tester) async {
final TextEditingController controller = TextEditingController( final TextEditingController controller = TextEditingController(
text: testValueA, text: testValueA,
); );
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
home: Center( home: Center(
...@@ -4882,12 +4959,13 @@ void main() { ...@@ -4882,12 +4959,13 @@ void main() {
variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android, TargetPlatform.fuchsia, TargetPlatform.linux }), variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android, TargetPlatform.fuchsia, TargetPlatform.linux }),
); );
testWidgets( testWidgetsWithLeakTracking(
'Double click and triple click alternate on Windows', 'Double click and triple click alternate on Windows',
(WidgetTester tester) async { (WidgetTester tester) async {
final TextEditingController controller = TextEditingController( final TextEditingController controller = TextEditingController(
text: testValueA, text: testValueA,
); );
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
home: Center( home: Center(
...@@ -5000,10 +5078,11 @@ void main() { ...@@ -5000,10 +5078,11 @@ void main() {
); );
}); });
testWidgets('force press selects word', (WidgetTester tester) async { testWidgetsWithLeakTracking('force press selects word', (WidgetTester tester) async {
final TextEditingController controller = TextEditingController( final TextEditingController controller = TextEditingController(
text: 'Atwater Peel Sherbrooke Bonaventure', text: 'Atwater Peel Sherbrooke Bonaventure',
); );
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
home: Center( home: Center(
...@@ -5055,10 +5134,11 @@ void main() { ...@@ -5055,10 +5134,11 @@ void main() {
expect(find.byType(CupertinoButton), matchToolbarButtons); expect(find.byType(CupertinoButton), matchToolbarButtons);
}); });
testWidgets('force press on unsupported devices falls back to tap', (WidgetTester tester) async { testWidgetsWithLeakTracking('force press on unsupported devices falls back to tap', (WidgetTester tester) async {
final TextEditingController controller = TextEditingController( final TextEditingController controller = TextEditingController(
text: 'Atwater Peel Sherbrooke Bonaventure', text: 'Atwater Peel Sherbrooke Bonaventure',
); );
addTearDown(controller.dispose);
// On iOS/iPadOS, during a tap we select the edge of the word closest to the tap. // On iOS/iPadOS, during a tap we select the edge of the word closest to the tap.
// On macOS, we select the precise position of the tap. // On macOS, we select the precise position of the tap.
final bool isTargetPlatformIOS = defaultTargetPlatform == TargetPlatform.iOS; final bool isTargetPlatformIOS = defaultTargetPlatform == TargetPlatform.iOS;
...@@ -5098,10 +5178,11 @@ void main() { ...@@ -5098,10 +5178,11 @@ void main() {
expect(find.byType(CupertinoButton), findsNothing); expect(find.byType(CupertinoButton), findsNothing);
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS })); }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
testWidgets('Cannot drag one handle past the other', (WidgetTester tester) async { testWidgetsWithLeakTracking('Cannot drag one handle past the other', (WidgetTester tester) async {
final TextEditingController controller = TextEditingController( final TextEditingController controller = TextEditingController(
text: 'abc def ghi', text: 'abc def ghi',
); );
addTearDown(controller.dispose);
// On iOS/iPadOS, during a tap we select the edge of the word closest to the tap. // On iOS/iPadOS, during a tap we select the edge of the word closest to the tap.
// On macOS, we select the precise position of the tap. // On macOS, we select the precise position of the tap.
final bool isTargetPlatformIOS = defaultTargetPlatform == TargetPlatform.iOS; final bool isTargetPlatformIOS = defaultTargetPlatform == TargetPlatform.iOS;
...@@ -5165,11 +5246,12 @@ void main() { ...@@ -5165,11 +5246,12 @@ void main() {
expect(controller.selection.extentOffset, 5); expect(controller.selection.extentOffset, 5);
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS })); }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS }));
testWidgets('Dragging between multiple lines keeps the contact point at the same place on the handle on Android', (WidgetTester tester) async { testWidgetsWithLeakTracking('Dragging between multiple lines keeps the contact point at the same place on the handle on Android', (WidgetTester tester) async {
final TextEditingController controller = TextEditingController( final TextEditingController controller = TextEditingController(
// 11 first line, 19 second line, 17 third line = length 49 // 11 first line, 19 second line, 17 third line = length 49
text: 'a big house\njumped over a mouse\nOne more line yay', text: 'a big house\njumped over a mouse\nOne more line yay',
); );
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
...@@ -5363,11 +5445,12 @@ void main() { ...@@ -5363,11 +5445,12 @@ void main() {
variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android }), variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android }),
); );
testWidgets('Dragging between multiple lines keeps the contact point at the same place on the handle on iOS', (WidgetTester tester) async { testWidgetsWithLeakTracking('Dragging between multiple lines keeps the contact point at the same place on the handle on iOS', (WidgetTester tester) async {
final TextEditingController controller = TextEditingController( final TextEditingController controller = TextEditingController(
// 11 first line, 19 second line, 17 third line = length 49 // 11 first line, 19 second line, 17 third line = length 49
text: 'a big house\njumped over a mouse\nOne more line yay', text: 'a big house\njumped over a mouse\nOne more line yay',
); );
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
...@@ -5552,8 +5635,9 @@ void main() { ...@@ -5552,8 +5635,9 @@ void main() {
variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS }), variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS }),
); );
testWidgets('Selection updates on tap down (Desktop platforms)', (WidgetTester tester) async { testWidgetsWithLeakTracking('Selection updates on tap down (Desktop platforms)', (WidgetTester tester) async {
final TextEditingController controller = TextEditingController(); final TextEditingController controller = TextEditingController();
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
...@@ -5593,8 +5677,9 @@ void main() { ...@@ -5593,8 +5677,9 @@ void main() {
variant: TargetPlatformVariant.desktop(), variant: TargetPlatformVariant.desktop(),
); );
testWidgets('Selection updates on tap up (Mobile platforms)', (WidgetTester tester) async { testWidgetsWithLeakTracking('Selection updates on tap up (Mobile platforms)', (WidgetTester tester) async {
final TextEditingController controller = TextEditingController(); final TextEditingController controller = TextEditingController();
addTearDown(controller.dispose);
final bool isTargetPlatformApple = defaultTargetPlatform == TargetPlatform.iOS; final bool isTargetPlatformApple = defaultTargetPlatform == TargetPlatform.iOS;
await tester.pumpWidget( await tester.pumpWidget(
...@@ -5649,8 +5734,9 @@ void main() { ...@@ -5649,8 +5734,9 @@ void main() {
variant: TargetPlatformVariant.mobile(), variant: TargetPlatformVariant.mobile(),
); );
testWidgets('Can select text by dragging with a mouse', (WidgetTester tester) async { testWidgetsWithLeakTracking('Can select text by dragging with a mouse', (WidgetTester tester) async {
final TextEditingController controller = TextEditingController(); final TextEditingController controller = TextEditingController();
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
...@@ -5684,8 +5770,9 @@ void main() { ...@@ -5684,8 +5770,9 @@ void main() {
expect(controller.selection.extentOffset, testValue.indexOf('g')); expect(controller.selection.extentOffset, testValue.indexOf('g'));
}); });
testWidgets('Cursor should not move on a quick touch drag when touch does not begin on previous selection (iOS)', (WidgetTester tester) async { testWidgetsWithLeakTracking('Cursor should not move on a quick touch drag when touch does not begin on previous selection (iOS)', (WidgetTester tester) async {
final TextEditingController controller = TextEditingController(); final TextEditingController controller = TextEditingController();
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
...@@ -5731,6 +5818,7 @@ void main() { ...@@ -5731,6 +5818,7 @@ void main() {
testWidgets('Can move cursor when dragging, when tap is on collapsed selection (iOS)', (WidgetTester tester) async { testWidgets('Can move cursor when dragging, when tap is on collapsed selection (iOS)', (WidgetTester tester) async {
final TextEditingController controller = TextEditingController(); final TextEditingController controller = TextEditingController();
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
...@@ -5778,6 +5866,7 @@ void main() { ...@@ -5778,6 +5866,7 @@ void main() {
testWidgets('Can move cursor when dragging, when tap is on collapsed selection (iOS) - multiline', (WidgetTester tester) async { testWidgets('Can move cursor when dragging, when tap is on collapsed selection (iOS) - multiline', (WidgetTester tester) async {
final TextEditingController controller = TextEditingController(); final TextEditingController controller = TextEditingController();
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
...@@ -5824,10 +5913,11 @@ void main() { ...@@ -5824,10 +5913,11 @@ void main() {
variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS }), variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS }),
); );
testWidgets('Can move cursor when dragging, when tap is on collapsed selection (iOS) - ListView', (WidgetTester tester) async { testWidgetsWithLeakTracking('Can move cursor when dragging, when tap is on collapsed selection (iOS) - ListView', (WidgetTester tester) async {
// This is a regression test for // This is a regression test for
// https://github.com/flutter/flutter/issues/122519 // https://github.com/flutter/flutter/issues/122519
final TextEditingController controller = TextEditingController(); final TextEditingController controller = TextEditingController();
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
...@@ -5902,6 +5992,7 @@ void main() { ...@@ -5902,6 +5992,7 @@ void main() {
testWidgets('Can move cursor when dragging (Android)', (WidgetTester tester) async { testWidgets('Can move cursor when dragging (Android)', (WidgetTester tester) async {
final TextEditingController controller = TextEditingController(); final TextEditingController controller = TextEditingController();
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
...@@ -5944,10 +6035,11 @@ void main() { ...@@ -5944,10 +6035,11 @@ void main() {
variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android, TargetPlatform.fuchsia }), variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android, TargetPlatform.fuchsia }),
); );
testWidgets('Continuous dragging does not cause flickering', (WidgetTester tester) async { testWidgetsWithLeakTracking('Continuous dragging does not cause flickering', (WidgetTester tester) async {
int selectionChangedCount = 0; int selectionChangedCount = 0;
const String testValue = 'abc def ghi'; const String testValue = 'abc def ghi';
final TextEditingController controller = TextEditingController(text: testValue); final TextEditingController controller = TextEditingController(text: testValue);
addTearDown(controller.dispose);
controller.addListener(() { controller.addListener(() {
selectionChangedCount++; selectionChangedCount++;
...@@ -5996,10 +6088,11 @@ void main() { ...@@ -5996,10 +6088,11 @@ void main() {
expect(controller.selection.extentOffset, 9); expect(controller.selection.extentOffset, 9);
}); });
testWidgets('Tap does not show handles nor toolbar', (WidgetTester tester) async { testWidgetsWithLeakTracking('Tap does not show handles nor toolbar', (WidgetTester tester) async {
final TextEditingController controller = TextEditingController( final TextEditingController controller = TextEditingController(
text: 'abc def ghi', text: 'abc def ghi',
); );
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
...@@ -6018,10 +6111,11 @@ void main() { ...@@ -6018,10 +6111,11 @@ void main() {
expect(editableText.selectionOverlay!.toolbarIsVisible, isFalse); expect(editableText.selectionOverlay!.toolbarIsVisible, isFalse);
}); });
testWidgets('Long press shows toolbar but not handles', (WidgetTester tester) async { testWidgetsWithLeakTracking('Long press shows toolbar but not handles', (WidgetTester tester) async {
final TextEditingController controller = TextEditingController( final TextEditingController controller = TextEditingController(
text: 'abc def ghi', text: 'abc def ghi',
); );
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
...@@ -6042,12 +6136,13 @@ void main() { ...@@ -6042,12 +6136,13 @@ void main() {
expect(editableText.selectionOverlay!.toolbarIsVisible, isContextMenuProvidedByPlatform ? isFalse : isTrue); expect(editableText.selectionOverlay!.toolbarIsVisible, isContextMenuProvidedByPlatform ? isFalse : isTrue);
}); });
testWidgets( testWidgetsWithLeakTracking(
'Double tap shows handles and toolbar if selection is not collapsed', 'Double tap shows handles and toolbar if selection is not collapsed',
(WidgetTester tester) async { (WidgetTester tester) async {
final TextEditingController controller = TextEditingController( final TextEditingController controller = TextEditingController(
text: 'abc def ghi', text: 'abc def ghi',
); );
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
...@@ -6071,12 +6166,13 @@ void main() { ...@@ -6071,12 +6166,13 @@ void main() {
}, },
); );
testWidgets( testWidgetsWithLeakTracking(
'Double tap shows toolbar but not handles if selection is collapsed', 'Double tap shows toolbar but not handles if selection is collapsed',
(WidgetTester tester) async { (WidgetTester tester) async {
final TextEditingController controller = TextEditingController( final TextEditingController controller = TextEditingController(
text: 'abc def ghi', text: 'abc def ghi',
); );
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
...@@ -6100,12 +6196,13 @@ void main() { ...@@ -6100,12 +6196,13 @@ void main() {
}, },
); );
testWidgets( testWidgetsWithLeakTracking(
'Mouse long press does not show handles nor toolbar', 'Mouse long press does not show handles nor toolbar',
(WidgetTester tester) async { (WidgetTester tester) async {
final TextEditingController controller = TextEditingController( final TextEditingController controller = TextEditingController(
text: 'abc def ghi', text: 'abc def ghi',
); );
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
...@@ -6131,12 +6228,13 @@ void main() { ...@@ -6131,12 +6228,13 @@ void main() {
}, },
); );
testWidgets( testWidgetsWithLeakTracking(
'Mouse double tap does not show handles nor toolbar', 'Mouse double tap does not show handles nor toolbar',
(WidgetTester tester) async { (WidgetTester tester) async {
final TextEditingController controller = TextEditingController( final TextEditingController controller = TextEditingController(
text: 'abc def ghi', text: 'abc def ghi',
); );
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
...@@ -6182,7 +6280,7 @@ void main() { ...@@ -6182,7 +6280,7 @@ void main() {
}, },
); );
testWidgets('onTap is called upon tap', (WidgetTester tester) async { testWidgetsWithLeakTracking('onTap is called upon tap', (WidgetTester tester) async {
int tapCount = 0; int tapCount = 0;
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
...@@ -6211,7 +6309,7 @@ void main() { ...@@ -6211,7 +6309,7 @@ void main() {
expect(tapCount, 2); expect(tapCount, 2);
}); });
testWidgets( testWidgetsWithLeakTracking(
'onTap does not work when the text field is disabled', 'onTap does not work when the text field is disabled',
(WidgetTester tester) async { (WidgetTester tester) async {
int tapCount = 0; int tapCount = 0;
...@@ -6268,8 +6366,9 @@ void main() { ...@@ -6268,8 +6366,9 @@ void main() {
}, },
); );
testWidgets('Focus test when the text field is disabled', (WidgetTester tester) async { testWidgetsWithLeakTracking('Focus test when the text field is disabled', (WidgetTester tester) async {
final FocusNode focusNode = FocusNode(); final FocusNode focusNode = FocusNode();
addTearDown(focusNode.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
home: Center( home: Center(
...@@ -6305,7 +6404,7 @@ void main() { ...@@ -6305,7 +6404,7 @@ void main() {
expect(focusNode.hasFocus, false); expect(focusNode.hasFocus, false);
}); });
testWidgets( testWidgetsWithLeakTracking(
'text field respects theme', 'text field respects theme',
(WidgetTester tester) async { (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
...@@ -6343,13 +6442,14 @@ void main() { ...@@ -6343,13 +6442,14 @@ void main() {
}, },
); );
testWidgets( testWidgetsWithLeakTracking(
'Check the toolbar appears below the TextField when there is not enough space above the TextField to show it', 'Check the toolbar appears below the TextField when there is not enough space above the TextField to show it',
(WidgetTester tester) async { (WidgetTester tester) async {
// This is a regression test for // This is a regression test for
// https://github.com/flutter/flutter/issues/29808 // https://github.com/flutter/flutter/issues/29808
const String testValue = 'abc def ghi'; const String testValue = 'abc def ghi';
final TextEditingController controller = TextEditingController(); final TextEditingController controller = TextEditingController();
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
...@@ -6414,7 +6514,7 @@ void main() { ...@@ -6414,7 +6514,7 @@ void main() {
skip: isContextMenuProvidedByPlatform, // [intended] only applies to platforms where we supply the context menu. skip: isContextMenuProvidedByPlatform, // [intended] only applies to platforms where we supply the context menu.
); );
testWidgets('text field respects keyboardAppearance from theme', (WidgetTester tester) async { testWidgetsWithLeakTracking('text field respects keyboardAppearance from theme', (WidgetTester tester) async {
final List<MethodCall> log = <MethodCall>[]; final List<MethodCall> log = <MethodCall>[];
tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.textInput, (MethodCall methodCall) async { tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.textInput, (MethodCall methodCall) async {
log.add(methodCall); log.add(methodCall);
...@@ -6438,7 +6538,7 @@ void main() { ...@@ -6438,7 +6538,7 @@ void main() {
expect(((setClient.arguments as List<dynamic>).last as Map<String, dynamic>)['keyboardAppearance'], 'Brightness.dark'); expect(((setClient.arguments as List<dynamic>).last as Map<String, dynamic>)['keyboardAppearance'], 'Brightness.dark');
}); });
testWidgets('text field can override keyboardAppearance from theme', (WidgetTester tester) async { testWidgetsWithLeakTracking('text field can override keyboardAppearance from theme', (WidgetTester tester) async {
final List<MethodCall> log = <MethodCall>[]; final List<MethodCall> log = <MethodCall>[];
tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.textInput, (MethodCall methodCall) async { tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.textInput, (MethodCall methodCall) async {
log.add(methodCall); log.add(methodCall);
...@@ -6464,7 +6564,7 @@ void main() { ...@@ -6464,7 +6564,7 @@ void main() {
expect(((setClient.arguments as List<dynamic>).last as Map<String, dynamic>)['keyboardAppearance'], 'Brightness.light'); expect(((setClient.arguments as List<dynamic>).last as Map<String, dynamic>)['keyboardAppearance'], 'Brightness.light');
}); });
testWidgets('cursorColor respects theme', (WidgetTester tester) async { testWidgetsWithLeakTracking('cursorColor respects theme', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
const CupertinoApp( const CupertinoApp(
home: CupertinoTextField(), home: CupertinoTextField(),
...@@ -6506,7 +6606,7 @@ void main() { ...@@ -6506,7 +6606,7 @@ void main() {
expect(renderEditable.cursorColor, const Color(0xFFF44336)); expect(renderEditable.cursorColor, const Color(0xFFF44336));
}); });
testWidgets('cursor can override color from theme', (WidgetTester tester) async { testWidgetsWithLeakTracking('cursor can override color from theme', (WidgetTester tester) async {
const CupertinoDynamicColor cursorColor = CupertinoDynamicColor.withBrightness( const CupertinoDynamicColor cursorColor = CupertinoDynamicColor.withBrightness(
color: Color(0x12345678), color: Color(0x12345678),
darkColor: Color(0x87654321), darkColor: Color(0x87654321),
...@@ -6541,9 +6641,10 @@ void main() { ...@@ -6541,9 +6641,10 @@ void main() {
expect(editableText.cursorColor.value, 0x87654321); expect(editableText.cursorColor.value, 0x87654321);
}); });
testWidgets('shows selection handles', (WidgetTester tester) async { testWidgetsWithLeakTracking('shows selection handles', (WidgetTester tester) async {
const String testText = 'lorem ipsum'; const String testText = 'lorem ipsum';
final TextEditingController controller = TextEditingController(text: testText); final TextEditingController controller = TextEditingController(text: testText);
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
...@@ -6573,9 +6674,11 @@ void main() { ...@@ -6573,9 +6674,11 @@ void main() {
expect(right.opacity.value, equals(1.0)); expect(right.opacity.value, equals(1.0));
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS })); }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
testWidgets('when CupertinoTextField would be blocked by keyboard, it is shown with enough space for the selection handle', (WidgetTester tester) async { testWidgetsWithLeakTracking('when CupertinoTextField would be blocked by keyboard, it is shown with enough space for the selection handle', (WidgetTester tester) async {
final ScrollController scrollController = ScrollController(); final ScrollController scrollController = ScrollController();
addTearDown(scrollController.dispose);
final TextEditingController controller = TextEditingController(); final TextEditingController controller = TextEditingController();
addTearDown(controller.dispose);
await tester.pumpWidget(CupertinoApp( await tester.pumpWidget(CupertinoApp(
theme: const CupertinoThemeData(), theme: const CupertinoThemeData(),
...@@ -6601,7 +6704,9 @@ void main() { ...@@ -6601,7 +6704,9 @@ void main() {
expect(scrollController.offset, 27.0); expect(scrollController.offset, 27.0);
}); });
testWidgets('disabled state golden', (WidgetTester tester) async { testWidgetsWithLeakTracking('disabled state golden', (WidgetTester tester) async {
final TextEditingController controller = TextEditingController(text: 'lorem');
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
home: DecoratedBox( home: DecoratedBox(
...@@ -6613,7 +6718,7 @@ void main() { ...@@ -6613,7 +6718,7 @@ void main() {
child: RepaintBoundary( child: RepaintBoundary(
key: const ValueKey<int>(1), key: const ValueKey<int>(1),
child: CupertinoTextField( child: CupertinoTextField(
controller: TextEditingController(text: 'lorem'), controller: controller,
enabled: false, enabled: false,
), ),
), ),
...@@ -6629,13 +6734,16 @@ void main() { ...@@ -6629,13 +6734,16 @@ void main() {
); );
}); });
testWidgets( testWidgetsWithLeakTracking(
'Can drag the left handle while the right handle remains off-screen', 'Can drag the left handle while the right handle remains off-screen',
(WidgetTester tester) async { (WidgetTester tester) async {
// Text is longer than textfield width. // Text is longer than textfield width.
const String testValue = 'aaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbb'; const String testValue = 'aaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbb';
final TextEditingController controller = TextEditingController(text: testValue); final TextEditingController controller = TextEditingController(text: testValue);
addTearDown(controller.dispose);
final ScrollController scrollController = ScrollController(); final ScrollController scrollController = ScrollController();
addTearDown(scrollController.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
...@@ -6712,13 +6820,15 @@ void main() { ...@@ -6712,13 +6820,15 @@ void main() {
}, },
); );
testWidgets( testWidgetsWithLeakTracking(
'Can drag the right handle while the left handle remains off-screen', 'Can drag the right handle while the left handle remains off-screen',
(WidgetTester tester) async { (WidgetTester tester) async {
// Text is longer than textfield width. // Text is longer than textfield width.
const String testValue = 'aaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbb'; const String testValue = 'aaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbb';
final TextEditingController controller = TextEditingController(text: testValue); final TextEditingController controller = TextEditingController(text: testValue);
addTearDown(controller.dispose);
final ScrollController scrollController = ScrollController(); final ScrollController scrollController = ScrollController();
addTearDown(scrollController.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
...@@ -6785,7 +6895,7 @@ void main() { ...@@ -6785,7 +6895,7 @@ void main() {
); );
group('Text selection toolbar', () { group('Text selection toolbar', () {
testWidgets('Collapsed selection works', (WidgetTester tester) async { testWidgetsWithLeakTracking('Collapsed selection works', (WidgetTester tester) async {
tester.view.physicalSize = const Size(400, 400); tester.view.physicalSize = const Size(400, 400);
tester.view.devicePixelRatio = 1; tester.view.devicePixelRatio = 1;
addTearDown(tester.view.reset); addTearDown(tester.view.reset);
...@@ -6858,6 +6968,7 @@ void main() { ...@@ -6858,6 +6968,7 @@ void main() {
// Top Right collapsed selection. The toolbar should flip vertically, and // Top Right collapsed selection. The toolbar should flip vertically, and
// the arrow should not point exactly to the caret because the caret is // the arrow should not point exactly to the caret because the caret is
// too close to the right. // too close to the right.
controller.dispose();
controller = TextEditingController(text: List<String>.filled(200, 'a').join()); controller = TextEditingController(text: List<String>.filled(200, 'a').join());
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
...@@ -6918,7 +7029,9 @@ void main() { ...@@ -6918,7 +7029,9 @@ void main() {
// Normal centered collapsed selection. The toolbar arrow should point down, and // Normal centered collapsed selection. The toolbar arrow should point down, and
// it should point exactly to the caret. // it should point exactly to the caret.
controller.dispose();
controller = TextEditingController(text: List<String>.filled(200, 'a').join()); controller = TextEditingController(text: List<String>.filled(200, 'a').join());
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
debugShowCheckedModeBanner: false, debugShowCheckedModeBanner: false,
...@@ -6971,7 +7084,7 @@ void main() { ...@@ -6971,7 +7084,7 @@ void main() {
); );
}); });
testWidgets('selecting multiple words works', (WidgetTester tester) async { testWidgetsWithLeakTracking('selecting multiple words works', (WidgetTester tester) async {
tester.view.physicalSize = const Size(400, 400); tester.view.physicalSize = const Size(400, 400);
tester.view.devicePixelRatio = 1; tester.view.devicePixelRatio = 1;
addTearDown(tester.view.reset); addTearDown(tester.view.reset);
...@@ -6983,6 +7096,7 @@ void main() { ...@@ -6983,6 +7096,7 @@ void main() {
// Normal multiword collapsed selection. The toolbar arrow should point down, and // Normal multiword collapsed selection. The toolbar arrow should point down, and
// it should point exactly to the caret. // it should point exactly to the caret.
controller = TextEditingController(text: List<String>.filled(20, 'a').join(' ')); controller = TextEditingController(text: List<String>.filled(20, 'a').join(' '));
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
debugShowCheckedModeBanner: false, debugShowCheckedModeBanner: false,
...@@ -7040,7 +7154,7 @@ void main() { ...@@ -7040,7 +7154,7 @@ void main() {
); );
}); });
testWidgets('selecting multiline works', (WidgetTester tester) async { testWidgetsWithLeakTracking('selecting multiline works', (WidgetTester tester) async {
tester.view.physicalSize = const Size(400, 400); tester.view.physicalSize = const Size(400, 400);
tester.view.devicePixelRatio = 1; tester.view.devicePixelRatio = 1;
addTearDown(tester.view.reset); addTearDown(tester.view.reset);
...@@ -7052,6 +7166,7 @@ void main() { ...@@ -7052,6 +7166,7 @@ void main() {
// Normal multiline collapsed selection. The toolbar arrow should point down, and // Normal multiline collapsed selection. The toolbar arrow should point down, and
// it should point exactly to the horizontal center of the text field. // it should point exactly to the horizontal center of the text field.
controller = TextEditingController(text: List<String>.filled(20, 'a a ').join('\n')); controller = TextEditingController(text: List<String>.filled(20, 'a a ').join('\n'));
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
debugShowCheckedModeBanner: false, debugShowCheckedModeBanner: false,
...@@ -7115,11 +7230,12 @@ void main() { ...@@ -7115,11 +7230,12 @@ void main() {
// This is a regression test for // This is a regression test for
// https://github.com/flutter/flutter/issues/37046. // https://github.com/flutter/flutter/issues/37046.
testWidgets('No exceptions when showing selection menu inside of nested Navigators', (WidgetTester tester) async { testWidgetsWithLeakTracking('No exceptions when showing selection menu inside of nested Navigators', (WidgetTester tester) async {
const String testValue = '123456'; const String testValue = '123456';
final TextEditingController controller = TextEditingController( final TextEditingController controller = TextEditingController(
text: testValue, text: testValue,
); );
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
home: CupertinoPageScaffold( home: CupertinoPageScaffold(
...@@ -7161,10 +7277,11 @@ void main() { ...@@ -7161,10 +7277,11 @@ void main() {
expect(tester.takeException(), null); expect(tester.takeException(), null);
}); });
testWidgets('Drag selection hides the selection menu', (WidgetTester tester) async { testWidgetsWithLeakTracking('Drag selection hides the selection menu', (WidgetTester tester) async {
final TextEditingController controller = TextEditingController( final TextEditingController controller = TextEditingController(
text: 'blah1 blah2', text: 'blah1 blah2',
); );
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
home: Center( home: Center(
...@@ -7211,8 +7328,9 @@ void main() { ...@@ -7211,8 +7328,9 @@ void main() {
group('textAlignVertical position', () { group('textAlignVertical position', () {
group('simple case', () { group('simple case', () {
testWidgets('align top (default)', (WidgetTester tester) async { testWidgetsWithLeakTracking('align top (default)', (WidgetTester tester) async {
final FocusNode focusNode = FocusNode(); final FocusNode focusNode = FocusNode();
addTearDown(focusNode.dispose);
const Size size = Size(200.0, 200.0); const Size size = Size(200.0, 200.0);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
...@@ -7257,8 +7375,9 @@ void main() { ...@@ -7257,8 +7375,9 @@ void main() {
expect(tester.getTopLeft(find.byType(EditableText)).dy, moreOrLessEquals(207.0, epsilon: .0001)); expect(tester.getTopLeft(find.byType(EditableText)).dy, moreOrLessEquals(207.0, epsilon: .0001));
}); });
testWidgets('align center', (WidgetTester tester) async { testWidgetsWithLeakTracking('align center', (WidgetTester tester) async {
final FocusNode focusNode = FocusNode(); final FocusNode focusNode = FocusNode();
addTearDown(focusNode.dispose);
const Size size = Size(200.0, 200.0); const Size size = Size(200.0, 200.0);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
...@@ -7304,8 +7423,9 @@ void main() { ...@@ -7304,8 +7423,9 @@ void main() {
expect(tester.getTopLeft(find.byType(EditableText)).dy, moreOrLessEquals(291.5, epsilon: .0001)); expect(tester.getTopLeft(find.byType(EditableText)).dy, moreOrLessEquals(291.5, epsilon: .0001));
}); });
testWidgets('align bottom', (WidgetTester tester) async { testWidgetsWithLeakTracking('align bottom', (WidgetTester tester) async {
final FocusNode focusNode = FocusNode(); final FocusNode focusNode = FocusNode();
addTearDown(focusNode.dispose);
const Size size = Size(200.0, 200.0); const Size size = Size(200.0, 200.0);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
...@@ -7351,8 +7471,9 @@ void main() { ...@@ -7351,8 +7471,9 @@ void main() {
expect(tester.getTopLeft(find.byType(EditableText)).dy, moreOrLessEquals(376.0, epsilon: .0001)); expect(tester.getTopLeft(find.byType(EditableText)).dy, moreOrLessEquals(376.0, epsilon: .0001));
}); });
testWidgets('align as a double', (WidgetTester tester) async { testWidgetsWithLeakTracking('align as a double', (WidgetTester tester) async {
final FocusNode focusNode = FocusNode(); final FocusNode focusNode = FocusNode();
addTearDown(focusNode.dispose);
const Size size = Size(200.0, 200.0); const Size size = Size(200.0, 200.0);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
...@@ -7400,8 +7521,9 @@ void main() { ...@@ -7400,8 +7521,9 @@ void main() {
}); });
group('tall prefix', () { group('tall prefix', () {
testWidgets('align center (default when prefix)', (WidgetTester tester) async { testWidgetsWithLeakTracking('align center (default when prefix)', (WidgetTester tester) async {
final FocusNode focusNode = FocusNode(); final FocusNode focusNode = FocusNode();
addTearDown(focusNode.dispose);
const Size size = Size(200.0, 200.0); const Size size = Size(200.0, 200.0);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
...@@ -7451,8 +7573,9 @@ void main() { ...@@ -7451,8 +7573,9 @@ void main() {
expect(tester.getTopLeft(find.byType(EditableText)).dy, moreOrLessEquals(291.5, epsilon: .0001)); expect(tester.getTopLeft(find.byType(EditableText)).dy, moreOrLessEquals(291.5, epsilon: .0001));
}); });
testWidgets('align top', (WidgetTester tester) async { testWidgetsWithLeakTracking('align top', (WidgetTester tester) async {
final FocusNode focusNode = FocusNode(); final FocusNode focusNode = FocusNode();
addTearDown(focusNode.dispose);
const Size size = Size(200.0, 200.0); const Size size = Size(200.0, 200.0);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
...@@ -7504,8 +7627,9 @@ void main() { ...@@ -7504,8 +7627,9 @@ void main() {
expect(tester.getTopLeft(find.byType(EditableText)).dy, moreOrLessEquals(241.5, epsilon: .0001)); expect(tester.getTopLeft(find.byType(EditableText)).dy, moreOrLessEquals(241.5, epsilon: .0001));
}); });
testWidgets('align bottom', (WidgetTester tester) async { testWidgetsWithLeakTracking('align bottom', (WidgetTester tester) async {
final FocusNode focusNode = FocusNode(); final FocusNode focusNode = FocusNode();
addTearDown(focusNode.dispose);
const Size size = Size(200.0, 200.0); const Size size = Size(200.0, 200.0);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
...@@ -7557,8 +7681,9 @@ void main() { ...@@ -7557,8 +7681,9 @@ void main() {
expect(tester.getTopLeft(find.byType(EditableText)).dy, moreOrLessEquals(341.5, epsilon: .0001)); expect(tester.getTopLeft(find.byType(EditableText)).dy, moreOrLessEquals(341.5, epsilon: .0001));
}); });
testWidgets('align as a double', (WidgetTester tester) async { testWidgetsWithLeakTracking('align as a double', (WidgetTester tester) async {
final FocusNode focusNode = FocusNode(); final FocusNode focusNode = FocusNode();
addTearDown(focusNode.dispose);
const Size size = Size(200.0, 200.0); const Size size = Size(200.0, 200.0);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
...@@ -7610,7 +7735,7 @@ void main() { ...@@ -7610,7 +7735,7 @@ void main() {
}); });
}); });
testWidgets( testWidgetsWithLeakTracking(
'Long press on an autofocused field shows the selection menu', 'Long press on an autofocused field shows the selection menu',
(WidgetTester tester) async { (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
...@@ -7637,7 +7762,7 @@ void main() { ...@@ -7637,7 +7762,7 @@ void main() {
); );
}); });
testWidgets("Arrow keys don't move input focus", (WidgetTester tester) async { testWidgetsWithLeakTracking("Arrow keys don't move input focus", (WidgetTester tester) async {
final TextEditingController controller1 = TextEditingController(); final TextEditingController controller1 = TextEditingController();
final TextEditingController controller2 = TextEditingController(); final TextEditingController controller2 = TextEditingController();
final TextEditingController controller3 = TextEditingController(); final TextEditingController controller3 = TextEditingController();
...@@ -7648,6 +7773,16 @@ void main() { ...@@ -7648,6 +7773,16 @@ void main() {
final FocusNode focusNode3 = FocusNode(debugLabel: 'Field 3'); final FocusNode focusNode3 = FocusNode(debugLabel: 'Field 3');
final FocusNode focusNode4 = FocusNode(debugLabel: 'Field 4'); final FocusNode focusNode4 = FocusNode(debugLabel: 'Field 4');
final FocusNode focusNode5 = FocusNode(debugLabel: 'Field 5'); final FocusNode focusNode5 = FocusNode(debugLabel: 'Field 5');
addTearDown(focusNode1.dispose);
addTearDown(focusNode2.dispose);
addTearDown(focusNode3.dispose);
addTearDown(focusNode4.dispose);
addTearDown(focusNode5.dispose);
addTearDown(controller1.dispose);
addTearDown(controller2.dispose);
addTearDown(controller3.dispose);
addTearDown(controller4.dispose);
addTearDown(controller5.dispose);
// Lay out text fields in a "+" formation, and focus the center one. // Lay out text fields in a "+" formation, and focus the center one.
await tester.pumpWidget(CupertinoApp( await tester.pumpWidget(CupertinoApp(
...@@ -7724,7 +7859,7 @@ void main() { ...@@ -7724,7 +7859,7 @@ void main() {
expect(focusNode3.hasPrimaryFocus, isTrue); expect(focusNode3.hasPrimaryFocus, isTrue);
}, variant: KeySimulatorTransitModeVariant.all()); }, variant: KeySimulatorTransitModeVariant.all());
testWidgets('Scrolling shortcuts are disabled in text fields', (WidgetTester tester) async { testWidgetsWithLeakTracking('Scrolling shortcuts are disabled in text fields', (WidgetTester tester) async {
bool scrollInvoked = false; bool scrollInvoked = false;
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
...@@ -7758,7 +7893,7 @@ void main() { ...@@ -7758,7 +7893,7 @@ void main() {
expect(scrollInvoked, isFalse); expect(scrollInvoked, isFalse);
}, variant: KeySimulatorTransitModeVariant.all()); }, variant: KeySimulatorTransitModeVariant.all());
testWidgets('Cupertino text field semantics', (WidgetTester tester) async { testWidgetsWithLeakTracking('Cupertino text field semantics', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
home: Center( home: Center(
...@@ -7786,7 +7921,7 @@ void main() { ...@@ -7786,7 +7921,7 @@ void main() {
); );
}); });
testWidgets('Disabled Cupertino text field semantics', (WidgetTester tester) async { testWidgetsWithLeakTracking('Disabled Cupertino text field semantics', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
home: Center( home: Center(
...@@ -7815,10 +7950,11 @@ void main() { ...@@ -7815,10 +7950,11 @@ void main() {
); );
}); });
testWidgets('text selection style 1', (WidgetTester tester) async { testWidgetsWithLeakTracking('text selection style 1', (WidgetTester tester) async {
final TextEditingController controller = TextEditingController( final TextEditingController controller = TextEditingController(
text: 'Atwater Peel Sherbrooke Bonaventure\nhi\nwassssup!', text: 'Atwater Peel Sherbrooke Bonaventure\nhi\nwassssup!',
); );
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
home: Center( home: Center(
...@@ -7869,10 +8005,11 @@ void main() { ...@@ -7869,10 +8005,11 @@ void main() {
skip: kIsWeb, // [intended] the web has its own Select All. skip: kIsWeb, // [intended] the web has its own Select All.
); );
testWidgets('text selection style 2', (WidgetTester tester) async { testWidgetsWithLeakTracking('text selection style 2', (WidgetTester tester) async {
final TextEditingController controller = TextEditingController( final TextEditingController controller = TextEditingController(
text: 'Atwater Peel Sherbrooke Bonaventure\nhi\nwassssup!', text: 'Atwater Peel Sherbrooke Bonaventure\nhi\nwassssup!',
); );
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
home: Center( home: Center(
...@@ -7922,7 +8059,7 @@ void main() { ...@@ -7922,7 +8059,7 @@ void main() {
skip: kIsWeb, // [intended] the web has its own Select All. skip: kIsWeb, // [intended] the web has its own Select All.
); );
testWidgets('textSelectionControls is passed to EditableText', (WidgetTester tester) async { testWidgetsWithLeakTracking('textSelectionControls is passed to EditableText', (WidgetTester tester) async {
final MockTextSelectionControls selectionControl = MockTextSelectionControls(); final MockTextSelectionControls selectionControl = MockTextSelectionControls();
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
...@@ -7938,7 +8075,7 @@ void main() { ...@@ -7938,7 +8075,7 @@ void main() {
expect(widget.selectionControls, equals(selectionControl)); expect(widget.selectionControls, equals(selectionControl));
}); });
testWidgets('Do not add LengthLimiting formatter to the user supplied list', (WidgetTester tester) async { testWidgetsWithLeakTracking('Do not add LengthLimiting formatter to the user supplied list', (WidgetTester tester) async {
final List<TextInputFormatter> formatters = <TextInputFormatter>[]; final List<TextInputFormatter> formatters = <TextInputFormatter>[];
await tester.pumpWidget( await tester.pumpWidget(
...@@ -7971,7 +8108,7 @@ void main() { ...@@ -7971,7 +8108,7 @@ void main() {
await tester.pumpAndSettle(); await tester.pumpAndSettle();
} }
testWidgets('using none enforcement.', (WidgetTester tester) async { testWidgetsWithLeakTracking('using none enforcement.', (WidgetTester tester) async {
const MaxLengthEnforcement enforcement = MaxLengthEnforcement.none; const MaxLengthEnforcement enforcement = MaxLengthEnforcement.none;
await setupWidget(tester, enforcement); await setupWidget(tester, enforcement);
...@@ -7991,7 +8128,7 @@ void main() { ...@@ -7991,7 +8128,7 @@ void main() {
expect(state.currentTextEditingValue.composing, TextRange.empty); expect(state.currentTextEditingValue.composing, TextRange.empty);
}); });
testWidgets('using enforced.', (WidgetTester tester) async { testWidgetsWithLeakTracking('using enforced.', (WidgetTester tester) async {
const MaxLengthEnforcement enforcement = MaxLengthEnforcement.enforced; const MaxLengthEnforcement enforcement = MaxLengthEnforcement.enforced;
await setupWidget(tester, enforcement); await setupWidget(tester, enforcement);
...@@ -8015,7 +8152,7 @@ void main() { ...@@ -8015,7 +8152,7 @@ void main() {
expect(state.currentTextEditingValue.composing, const TextRange(start: 3, end: 5)); expect(state.currentTextEditingValue.composing, const TextRange(start: 3, end: 5));
}); });
testWidgets('using truncateAfterCompositionEnds.', (WidgetTester tester) async { testWidgetsWithLeakTracking('using truncateAfterCompositionEnds.', (WidgetTester tester) async {
const MaxLengthEnforcement enforcement = MaxLengthEnforcement.truncateAfterCompositionEnds; const MaxLengthEnforcement enforcement = MaxLengthEnforcement.truncateAfterCompositionEnds;
await setupWidget(tester, enforcement); await setupWidget(tester, enforcement);
...@@ -8039,7 +8176,7 @@ void main() { ...@@ -8039,7 +8176,7 @@ void main() {
expect(state.currentTextEditingValue.composing, TextRange.empty); expect(state.currentTextEditingValue.composing, TextRange.empty);
}); });
testWidgets('using default behavior for different platforms.', (WidgetTester tester) async { testWidgetsWithLeakTracking('using default behavior for different platforms.', (WidgetTester tester) async {
await setupWidget(tester, null); await setupWidget(tester, null);
final EditableTextState state = tester.state(find.byType(EditableText)); final EditableTextState state = tester.state(find.byType(EditableText));
...@@ -8072,7 +8209,7 @@ void main() { ...@@ -8072,7 +8209,7 @@ void main() {
}); });
}); });
testWidgets('disabled widget changes background color', (WidgetTester tester) async { testWidgetsWithLeakTracking('disabled widget changes background color', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
const CupertinoApp( const CupertinoApp(
home: Center( home: Center(
...@@ -8148,7 +8285,7 @@ void main() { ...@@ -8148,7 +8285,7 @@ void main() {
}); });
// Regression test for https://github.com/flutter/flutter/issues/78097. // Regression test for https://github.com/flutter/flutter/issues/78097.
testWidgets( testWidgetsWithLeakTracking(
'still gets disabled background color when decoration is null', 'still gets disabled background color when decoration is null',
(WidgetTester tester) async { (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
...@@ -8172,7 +8309,7 @@ void main() { ...@@ -8172,7 +8309,7 @@ void main() {
}, },
); );
testWidgets('autofill info has placeholder text', (WidgetTester tester) async { testWidgetsWithLeakTracking('autofill info has placeholder text', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
const CupertinoApp( const CupertinoApp(
home: CupertinoTextField( home: CupertinoTextField(
...@@ -8188,7 +8325,7 @@ void main() { ...@@ -8188,7 +8325,7 @@ void main() {
); );
}); });
testWidgets('textDirection is passed to EditableText', (WidgetTester tester) async { testWidgetsWithLeakTracking('textDirection is passed to EditableText', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
const CupertinoApp( const CupertinoApp(
home: Center( home: Center(
...@@ -8216,7 +8353,7 @@ void main() { ...@@ -8216,7 +8353,7 @@ void main() {
expect(rtlWidget.textDirection, TextDirection.rtl); expect(rtlWidget.textDirection, TextDirection.rtl);
}); });
testWidgets('clipBehavior has expected defaults', (WidgetTester tester) async { testWidgetsWithLeakTracking('clipBehavior has expected defaults', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
const CupertinoApp( const CupertinoApp(
home: CupertinoTextField( home: CupertinoTextField(
...@@ -8228,7 +8365,9 @@ void main() { ...@@ -8228,7 +8365,9 @@ void main() {
expect(textField.clipBehavior, Clip.hardEdge); expect(textField.clipBehavior, Clip.hardEdge);
}); });
testWidgets('Overflow clipBehavior none golden', (WidgetTester tester) async { testWidgetsWithLeakTracking('Overflow clipBehavior none golden', (WidgetTester tester) async {
final OverflowWidgetTextEditingController controller = OverflowWidgetTextEditingController();
addTearDown(controller.dispose);
final Widget widget = CupertinoApp( final Widget widget = CupertinoApp(
home: RepaintBoundary( home: RepaintBoundary(
key: const ValueKey<int>(1), key: const ValueKey<int>(1),
...@@ -8240,7 +8379,7 @@ void main() { ...@@ -8240,7 +8379,7 @@ void main() {
// Make sure the input field is not high enough for the WidgetSpan. // Make sure the input field is not high enough for the WidgetSpan.
height: 50, height: 50,
child: CupertinoTextField( child: CupertinoTextField(
controller: OverflowWidgetTextEditingController(), controller: controller,
clipBehavior: Clip.none, clipBehavior: Clip.none,
), ),
), ),
...@@ -8262,10 +8401,11 @@ void main() { ...@@ -8262,10 +8401,11 @@ void main() {
); );
}); });
testWidgets('can shift + tap to select with a keyboard (Apple platforms)', (WidgetTester tester) async { testWidgetsWithLeakTracking('can shift + tap to select with a keyboard (Apple platforms)', (WidgetTester tester) async {
final TextEditingController controller = TextEditingController( final TextEditingController controller = TextEditingController(
text: 'Atwater Peel Sherbrooke Bonaventure', text: 'Atwater Peel Sherbrooke Bonaventure',
); );
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
home: Center( home: Center(
...@@ -8305,10 +8445,11 @@ void main() { ...@@ -8305,10 +8445,11 @@ void main() {
expect(controller.selection.extentOffset, 4); expect(controller.selection.extentOffset, 4);
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS })); }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
testWidgets('can shift + tap to select with a keyboard (non-Apple platforms)', (WidgetTester tester) async { testWidgetsWithLeakTracking('can shift + tap to select with a keyboard (non-Apple platforms)', (WidgetTester tester) async {
final TextEditingController controller = TextEditingController( final TextEditingController controller = TextEditingController(
text: 'Atwater Peel Sherbrooke Bonaventure', text: 'Atwater Peel Sherbrooke Bonaventure',
); );
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
home: Center( home: Center(
...@@ -8350,11 +8491,13 @@ void main() { ...@@ -8350,11 +8491,13 @@ void main() {
expect(controller.selection.extentOffset, 4); expect(controller.selection.extentOffset, 4);
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android, TargetPlatform.fuchsia, TargetPlatform.linux, TargetPlatform.windows })); }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android, TargetPlatform.fuchsia, TargetPlatform.linux, TargetPlatform.windows }));
testWidgets('shift tapping an unfocused field', (WidgetTester tester) async { testWidgetsWithLeakTracking('shift tapping an unfocused field', (WidgetTester tester) async {
final TextEditingController controller = TextEditingController( final TextEditingController controller = TextEditingController(
text: 'Atwater Peel Sherbrooke Bonaventure', text: 'Atwater Peel Sherbrooke Bonaventure',
); );
addTearDown(controller.dispose);
final FocusNode focusNode = FocusNode(); final FocusNode focusNode = FocusNode();
addTearDown(focusNode.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
home: Center( home: Center(
...@@ -8404,10 +8547,11 @@ void main() { ...@@ -8404,10 +8547,11 @@ void main() {
expect(controller.selection.extentOffset, 20); expect(controller.selection.extentOffset, 20);
}, variant: TargetPlatformVariant.all()); }, variant: TargetPlatformVariant.all());
testWidgets('can shift + tap + drag to select with a keyboard (Apple platforms)', (WidgetTester tester) async { testWidgetsWithLeakTracking('can shift + tap + drag to select with a keyboard (Apple platforms)', (WidgetTester tester) async {
final TextEditingController controller = TextEditingController( final TextEditingController controller = TextEditingController(
text: 'Atwater Peel Sherbrooke Bonaventure', text: 'Atwater Peel Sherbrooke Bonaventure',
); );
addTearDown(controller.dispose);
final bool isTargetPlatformIOS = defaultTargetPlatform == TargetPlatform.iOS; final bool isTargetPlatformIOS = defaultTargetPlatform == TargetPlatform.iOS;
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
...@@ -8510,10 +8654,11 @@ void main() { ...@@ -8510,10 +8654,11 @@ void main() {
expect(controller.selection.extentOffset, 26); expect(controller.selection.extentOffset, 26);
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS })); }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
testWidgets('can shift + tap + drag to select with a keyboard (non-Apple platforms)', (WidgetTester tester) async { testWidgetsWithLeakTracking('can shift + tap + drag to select with a keyboard (non-Apple platforms)', (WidgetTester tester) async {
final TextEditingController controller = TextEditingController( final TextEditingController controller = TextEditingController(
text: 'Atwater Peel Sherbrooke Bonaventure', text: 'Atwater Peel Sherbrooke Bonaventure',
); );
addTearDown(controller.dispose);
final bool isTargetPlatformMobile = defaultTargetPlatform == TargetPlatform.android final bool isTargetPlatformMobile = defaultTargetPlatform == TargetPlatform.android
|| defaultTargetPlatform == TargetPlatform.fuchsia; || defaultTargetPlatform == TargetPlatform.fuchsia;
await tester.pumpWidget( await tester.pumpWidget(
...@@ -8617,10 +8762,11 @@ void main() { ...@@ -8617,10 +8762,11 @@ void main() {
expect(controller.selection.extentOffset, 26); expect(controller.selection.extentOffset, 26);
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.linux, TargetPlatform.android, TargetPlatform.fuchsia, TargetPlatform.windows })); }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.linux, TargetPlatform.android, TargetPlatform.fuchsia, TargetPlatform.windows }));
testWidgets('can shift + tap + drag to select with a keyboard, reversed (Apple platforms)', (WidgetTester tester) async { testWidgetsWithLeakTracking('can shift + tap + drag to select with a keyboard, reversed (Apple platforms)', (WidgetTester tester) async {
final TextEditingController controller = TextEditingController( final TextEditingController controller = TextEditingController(
text: 'Atwater Peel Sherbrooke Bonaventure', text: 'Atwater Peel Sherbrooke Bonaventure',
); );
addTearDown(controller.dispose);
final bool isTargetPlatformIOS = defaultTargetPlatform == TargetPlatform.iOS; final bool isTargetPlatformIOS = defaultTargetPlatform == TargetPlatform.iOS;
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
...@@ -8724,10 +8870,11 @@ void main() { ...@@ -8724,10 +8870,11 @@ void main() {
expect(controller.selection.extentOffset, 14); expect(controller.selection.extentOffset, 14);
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS })); }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
testWidgets('can shift + tap + drag to select with a keyboard, reversed (non-Apple platforms)', (WidgetTester tester) async { testWidgetsWithLeakTracking('can shift + tap + drag to select with a keyboard, reversed (non-Apple platforms)', (WidgetTester tester) async {
final TextEditingController controller = TextEditingController( final TextEditingController controller = TextEditingController(
text: 'Atwater Peel Sherbrooke Bonaventure', text: 'Atwater Peel Sherbrooke Bonaventure',
); );
addTearDown(controller.dispose);
final bool isTargetPlatformMobile = defaultTargetPlatform == TargetPlatform.android final bool isTargetPlatformMobile = defaultTargetPlatform == TargetPlatform.android
|| defaultTargetPlatform == TargetPlatform.fuchsia; || defaultTargetPlatform == TargetPlatform.fuchsia;
await tester.pumpWidget( await tester.pumpWidget(
...@@ -8832,10 +8979,11 @@ void main() { ...@@ -8832,10 +8979,11 @@ void main() {
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.linux, TargetPlatform.android, TargetPlatform.fuchsia, TargetPlatform.windows })); }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.linux, TargetPlatform.android, TargetPlatform.fuchsia, TargetPlatform.windows }));
// Regression test for https://github.com/flutter/flutter/issues/101587. // Regression test for https://github.com/flutter/flutter/issues/101587.
testWidgets('Right clicking menu behavior', (WidgetTester tester) async { testWidgetsWithLeakTracking('Right clicking menu behavior', (WidgetTester tester) async {
final TextEditingController controller = TextEditingController( final TextEditingController controller = TextEditingController(
text: 'blah1 blah2', text: 'blah1 blah2',
); );
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
home: Center( home: Center(
...@@ -8910,10 +9058,12 @@ void main() { ...@@ -8910,10 +9058,12 @@ void main() {
); );
group('Right click focus', () { group('Right click focus', () {
testWidgets('Can right click to focus multiple times', (WidgetTester tester) async { testWidgetsWithLeakTracking('Can right click to focus multiple times', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/pull/103228 // Regression test for https://github.com/flutter/flutter/pull/103228
final FocusNode focusNode1 = FocusNode(); final FocusNode focusNode1 = FocusNode();
final FocusNode focusNode2 = FocusNode(); final FocusNode focusNode2 = FocusNode();
addTearDown(focusNode1.dispose);
addTearDown(focusNode2.dispose);
final UniqueKey key1 = UniqueKey(); final UniqueKey key1 = UniqueKey();
final UniqueKey key2 = UniqueKey(); final UniqueKey key2 = UniqueKey();
await tester.pumpWidget( await tester.pumpWidget(
...@@ -8965,12 +9115,15 @@ void main() { ...@@ -8965,12 +9115,15 @@ void main() {
expect(focusNode2.hasFocus, isFalse); expect(focusNode2.hasFocus, isFalse);
}); });
testWidgets('Can right click to focus on previously selected word on Apple platforms', (WidgetTester tester) async { testWidgetsWithLeakTracking('Can right click to focus on previously selected word on Apple platforms', (WidgetTester tester) async {
final FocusNode focusNode1 = FocusNode(); final FocusNode focusNode1 = FocusNode();
final FocusNode focusNode2 = FocusNode(); final FocusNode focusNode2 = FocusNode();
addTearDown(focusNode1.dispose);
addTearDown(focusNode2.dispose);
final TextEditingController controller = TextEditingController( final TextEditingController controller = TextEditingController(
text: 'first second', text: 'first second',
); );
addTearDown(controller.dispose);
final UniqueKey key1 = UniqueKey(); final UniqueKey key1 = UniqueKey();
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
...@@ -9065,8 +9218,9 @@ void main() { ...@@ -9065,8 +9218,9 @@ void main() {
}); });
group('context menu', () { group('context menu', () {
testWidgets('builds CupertinoAdaptiveTextSelectionToolbar by default', (WidgetTester tester) async { testWidgetsWithLeakTracking('builds CupertinoAdaptiveTextSelectionToolbar by default', (WidgetTester tester) async {
final TextEditingController controller = TextEditingController(text: ''); final TextEditingController controller = TextEditingController(text: '');
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
home: Column( home: Column(
...@@ -9095,9 +9249,10 @@ void main() { ...@@ -9095,9 +9249,10 @@ void main() {
skip: kIsWeb, // [intended] on web the browser handles the context menu. skip: kIsWeb, // [intended] on web the browser handles the context menu.
); );
testWidgets('contextMenuBuilder is used in place of the default text selection toolbar', (WidgetTester tester) async { testWidgetsWithLeakTracking('contextMenuBuilder is used in place of the default text selection toolbar', (WidgetTester tester) async {
final GlobalKey key = GlobalKey(); final GlobalKey key = GlobalKey();
final TextEditingController controller = TextEditingController(text: ''); final TextEditingController controller = TextEditingController(text: '');
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
home: Column( home: Column(
...@@ -9138,7 +9293,7 @@ void main() { ...@@ -9138,7 +9293,7 @@ void main() {
final Widget fakeMagnifier = Container(key: UniqueKey()); final Widget fakeMagnifier = Container(key: UniqueKey());
group('magnifier builder', () { group('magnifier builder', () {
testWidgets('should build custom magnifier if given', (WidgetTester tester) async { testWidgetsWithLeakTracking('should build custom magnifier if given', (WidgetTester tester) async {
final Widget customMagnifier = Container( final Widget customMagnifier = Container(
key: UniqueKey(), key: UniqueKey(),
); );
...@@ -9153,17 +9308,19 @@ void main() { ...@@ -9153,17 +9308,19 @@ void main() {
final BuildContext context = final BuildContext context =
tester.firstElement(find.byType(Placeholder)); tester.firstElement(find.byType(Placeholder));
final ValueNotifier<MagnifierInfo> magnifierInfo = ValueNotifier<MagnifierInfo>(MagnifierInfo.empty);
addTearDown(magnifierInfo.dispose);
expect( expect(
defaultCupertinoTextField.magnifierConfiguration!.magnifierBuilder( defaultCupertinoTextField.magnifierConfiguration!.magnifierBuilder(
context, context,
MagnifierController(), MagnifierController(),
ValueNotifier<MagnifierInfo>(MagnifierInfo.empty), magnifierInfo,
), ),
isA<Widget>().having((Widget widget) => widget.key, 'key', equals(customMagnifier.key))); isA<Widget>().having((Widget widget) => widget.key, 'key', equals(customMagnifier.key)));
}); });
group('defaults', () { group('defaults', () {
testWidgets('should build CupertinoMagnifier on iOS and Android', (WidgetTester tester) async { testWidgetsWithLeakTracking('should build CupertinoMagnifier on iOS and Android', (WidgetTester tester) async {
await tester.pumpWidget(const CupertinoApp( await tester.pumpWidget(const CupertinoApp(
home: CupertinoTextField(), home: CupertinoTextField(),
)); ));
...@@ -9171,11 +9328,13 @@ void main() { ...@@ -9171,11 +9328,13 @@ void main() {
final BuildContext context = tester.firstElement(find.byType(CupertinoTextField)); final BuildContext context = tester.firstElement(find.byType(CupertinoTextField));
final EditableText editableText = tester.widget(find.byType(EditableText)); final EditableText editableText = tester.widget(find.byType(EditableText));
final ValueNotifier<MagnifierInfo> magnifierInfo = ValueNotifier<MagnifierInfo>(MagnifierInfo.empty);
addTearDown(magnifierInfo.dispose);
expect( expect(
editableText.magnifierConfiguration.magnifierBuilder( editableText.magnifierConfiguration.magnifierBuilder(
context, context,
MagnifierController(), MagnifierController(),
ValueNotifier<MagnifierInfo>(MagnifierInfo.empty), magnifierInfo,
), ),
isA<CupertinoTextMagnifier>()); isA<CupertinoTextMagnifier>());
}, },
...@@ -9183,7 +9342,7 @@ void main() { ...@@ -9183,7 +9342,7 @@ void main() {
<TargetPlatform>{TargetPlatform.iOS, TargetPlatform.android})); <TargetPlatform>{TargetPlatform.iOS, TargetPlatform.android}));
}); });
testWidgets('should build nothing on all platforms but iOS and Android', (WidgetTester tester) async { testWidgetsWithLeakTracking('should build nothing on all platforms but iOS and Android', (WidgetTester tester) async {
await tester.pumpWidget(const CupertinoApp( await tester.pumpWidget(const CupertinoApp(
home: CupertinoTextField(), home: CupertinoTextField(),
)); ));
...@@ -9191,11 +9350,13 @@ void main() { ...@@ -9191,11 +9350,13 @@ void main() {
final BuildContext context = tester.firstElement(find.byType(CupertinoTextField)); final BuildContext context = tester.firstElement(find.byType(CupertinoTextField));
final EditableText editableText = tester.widget(find.byType(EditableText)); final EditableText editableText = tester.widget(find.byType(EditableText));
final ValueNotifier<MagnifierInfo> magnifierInfo = ValueNotifier<MagnifierInfo>(MagnifierInfo.empty);
addTearDown(magnifierInfo.dispose);
expect( expect(
editableText.magnifierConfiguration.magnifierBuilder( editableText.magnifierConfiguration.magnifierBuilder(
context, context,
MagnifierController(), MagnifierController(),
ValueNotifier<MagnifierInfo>(MagnifierInfo.empty), magnifierInfo,
), ),
isNull); isNull);
}, },
...@@ -9203,9 +9364,10 @@ void main() { ...@@ -9203,9 +9364,10 @@ void main() {
excluding: <TargetPlatform>{TargetPlatform.iOS, TargetPlatform.android})); excluding: <TargetPlatform>{TargetPlatform.iOS, TargetPlatform.android}));
}); });
testWidgets('Can drag handles to show, unshow, and update magnifier', testWidgetsWithLeakTracking('Can drag handles to show, unshow, and update magnifier',
(WidgetTester tester) async { (WidgetTester tester) async {
final TextEditingController controller = TextEditingController(); final TextEditingController controller = TextEditingController();
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
home: CupertinoPageScaffold( home: CupertinoPageScaffold(
...@@ -9270,8 +9432,9 @@ void main() { ...@@ -9270,8 +9432,9 @@ void main() {
expect(find.byKey(fakeMagnifier.key!), findsNothing); expect(find.byKey(fakeMagnifier.key!), findsNothing);
}, variant: TargetPlatformVariant.only(TargetPlatform.iOS)); }, variant: TargetPlatformVariant.only(TargetPlatform.iOS));
testWidgets('Can drag to show, unshow, and update magnifier', (WidgetTester tester) async { testWidgetsWithLeakTracking('Can drag to show, unshow, and update magnifier', (WidgetTester tester) async {
final TextEditingController controller = TextEditingController(); final TextEditingController controller = TextEditingController();
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
home: Center( home: Center(
...@@ -9369,8 +9532,9 @@ void main() { ...@@ -9369,8 +9532,9 @@ void main() {
expect(find.byKey(fakeMagnifier.key!), findsNothing); expect(find.byKey(fakeMagnifier.key!), findsNothing);
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android, TargetPlatform.iOS })); }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android, TargetPlatform.iOS }));
testWidgets('Can long press to show, unshow, and update magnifier on non-Apple platforms', (WidgetTester tester) async { testWidgetsWithLeakTracking('Can long press to show, unshow, and update magnifier on non-Apple platforms', (WidgetTester tester) async {
final TextEditingController controller = TextEditingController(); final TextEditingController controller = TextEditingController();
addTearDown(controller.dispose);
final bool isTargetPlatformAndroid = defaultTargetPlatform == TargetPlatform.android; final bool isTargetPlatformAndroid = defaultTargetPlatform == TargetPlatform.android;
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
...@@ -9428,8 +9592,9 @@ void main() { ...@@ -9428,8 +9592,9 @@ void main() {
expect(find.byKey(fakeMagnifier.key!), findsNothing); expect(find.byKey(fakeMagnifier.key!), findsNothing);
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android })); }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android }));
testWidgets('Can long press to show, unshow, and update magnifier on iOS', (WidgetTester tester) async { testWidgetsWithLeakTracking('Can long press to show, unshow, and update magnifier on iOS', (WidgetTester tester) async {
final TextEditingController controller = TextEditingController(); final TextEditingController controller = TextEditingController();
addTearDown(controller.dispose);
final bool isTargetPlatformAndroid = defaultTargetPlatform == TargetPlatform.android; final bool isTargetPlatformAndroid = defaultTargetPlatform == TargetPlatform.android;
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
...@@ -9490,8 +9655,9 @@ void main() { ...@@ -9490,8 +9655,9 @@ void main() {
}); });
group('TapRegion integration', () { group('TapRegion integration', () {
testWidgets('Tapping outside loses focus on desktop', (WidgetTester tester) async { testWidgetsWithLeakTracking('Tapping outside loses focus on desktop', (WidgetTester tester) async {
final FocusNode focusNode = FocusNode(debugLabel: 'Test Node'); final FocusNode focusNode = FocusNode(debugLabel: 'Test Node');
addTearDown(focusNode.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
home: Center( home: Center(
...@@ -9516,8 +9682,9 @@ void main() { ...@@ -9516,8 +9682,9 @@ void main() {
expect(focusNode.hasPrimaryFocus, isFalse); expect(focusNode.hasPrimaryFocus, isFalse);
}, variant: TargetPlatformVariant.desktop()); }, variant: TargetPlatformVariant.desktop());
testWidgets("Tapping outside doesn't lose focus on mobile", (WidgetTester tester) async { testWidgetsWithLeakTracking("Tapping outside doesn't lose focus on mobile", (WidgetTester tester) async {
final FocusNode focusNode = FocusNode(debugLabel: 'Test Node'); final FocusNode focusNode = FocusNode(debugLabel: 'Test Node');
addTearDown(focusNode.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
home: Center( home: Center(
...@@ -9543,12 +9710,14 @@ void main() { ...@@ -9543,12 +9710,14 @@ void main() {
expect(focusNode.hasPrimaryFocus, kIsWeb ? isFalse : isTrue); expect(focusNode.hasPrimaryFocus, kIsWeb ? isFalse : isTrue);
}, variant: TargetPlatformVariant.mobile()); }, variant: TargetPlatformVariant.mobile());
testWidgets("tapping on toolbar doesn't lose focus", (WidgetTester tester) async { testWidgetsWithLeakTracking("tapping on toolbar doesn't lose focus", (WidgetTester tester) async {
final TextEditingController controller; final TextEditingController controller;
final EditableTextState state; final EditableTextState state;
controller = TextEditingController(text: 'A B C'); controller = TextEditingController(text: 'A B C');
addTearDown(controller.dispose);
final FocusNode focusNode = FocusNode(debugLabel: 'Test Node'); final FocusNode focusNode = FocusNode(debugLabel: 'Test Node');
addTearDown(focusNode.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
debugShowCheckedModeBanner: false, debugShowCheckedModeBanner: false,
...@@ -9602,9 +9771,10 @@ void main() { ...@@ -9602,9 +9771,10 @@ void main() {
skip: kIsWeb, // [intended] The toolbar isn't rendered by Flutter on the web, it's rendered by the browser. skip: kIsWeb, // [intended] The toolbar isn't rendered by Flutter on the web, it's rendered by the browser.
); );
testWidgets("Tapping on border doesn't lose focus", testWidgetsWithLeakTracking("Tapping on border doesn't lose focus",
(WidgetTester tester) async { (WidgetTester tester) async {
final FocusNode focusNode = FocusNode(debugLabel: 'Test Node'); final FocusNode focusNode = FocusNode(debugLabel: 'Test Node');
addTearDown(focusNode.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
home: Center( home: Center(
...@@ -9631,8 +9801,9 @@ void main() { ...@@ -9631,8 +9801,9 @@ void main() {
}, variant: TargetPlatformVariant.all()); }, variant: TargetPlatformVariant.all());
}); });
testWidgets('Can drag handles to change selection correctly in multiline', (WidgetTester tester) async { testWidgetsWithLeakTracking('Can drag handles to change selection correctly in multiline', (WidgetTester tester) async {
final TextEditingController controller = TextEditingController(); final TextEditingController controller = TextEditingController();
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
...@@ -9728,7 +9899,7 @@ void main() { ...@@ -9728,7 +9899,7 @@ void main() {
} }
}); });
testWidgets('placeholder style overflow works', (WidgetTester tester) async { testWidgetsWithLeakTracking('placeholder style overflow works', (WidgetTester tester) async {
final String placeholder = 'hint text' * 20; final String placeholder = 'hint text' * 20;
const TextStyle placeholderStyle = TextStyle( const TextStyle placeholderStyle = TextStyle(
fontSize: 14.0, fontSize: 14.0,
...@@ -9752,7 +9923,7 @@ void main() { ...@@ -9752,7 +9923,7 @@ void main() {
expect(placeholderWidget.style!.overflow, placeholderStyle.overflow); expect(placeholderWidget.style!.overflow, placeholderStyle.overflow);
}); });
testWidgets('tapping on a misspelled word on iOS hides the handles and shows red selection', (WidgetTester tester) async { testWidgetsWithLeakTracking('tapping on a misspelled word on iOS hides the handles and shows red selection', (WidgetTester tester) async {
tester.binding.platformDispatcher.nativeSpellCheckServiceDefinedTestValue = tester.binding.platformDispatcher.nativeSpellCheckServiceDefinedTestValue =
true; true;
// The default derived color for the iOS text selection highlight. // The default derived color for the iOS text selection highlight.
...@@ -9760,6 +9931,7 @@ void main() { ...@@ -9760,6 +9931,7 @@ void main() {
final TextEditingController controller = TextEditingController( final TextEditingController controller = TextEditingController(
text: 'test test testt', text: 'test test testt',
); );
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
home: Center( home: Center(
...@@ -9825,10 +9997,11 @@ void main() { ...@@ -9825,10 +9997,11 @@ void main() {
skip: kIsWeb, // [intended] skip: kIsWeb, // [intended]
); );
testWidgets('text selection toolbar is hidden on tap down', (WidgetTester tester) async { testWidgetsWithLeakTracking('text selection toolbar is hidden on tap down', (WidgetTester tester) async {
final TextEditingController controller = TextEditingController( final TextEditingController controller = TextEditingController(
text: 'blah1 blah2', text: 'blah1 blah2',
); );
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
home: Center( home: Center(
...@@ -9870,9 +10043,10 @@ void main() { ...@@ -9870,9 +10043,10 @@ void main() {
variant: TargetPlatformVariant.all(excluding: <TargetPlatform>{ TargetPlatform.iOS }), variant: TargetPlatformVariant.all(excluding: <TargetPlatform>{ TargetPlatform.iOS }),
); );
testWidgets('Does not shrink in height when enters text when there is large single-line placeholder', (WidgetTester tester) async { testWidgetsWithLeakTracking('Does not shrink in height when enters text when there is large single-line placeholder', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/133241. // Regression test for https://github.com/flutter/flutter/issues/133241.
final TextEditingController controller = TextEditingController(); final TextEditingController controller = TextEditingController();
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
home: Align( home: Align(
...@@ -9894,8 +10068,9 @@ void main() { ...@@ -9894,8 +10068,9 @@ void main() {
expect(rectWithPlaceholder, rectWithText); expect(rectWithPlaceholder, rectWithText);
}); });
testWidgets('Does not match the height of a multiline placeholder', (WidgetTester tester) async { testWidgetsWithLeakTracking('Does not match the height of a multiline placeholder', (WidgetTester tester) async {
final TextEditingController controller = TextEditingController(); final TextEditingController controller = TextEditingController();
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
home: Align( home: Align(
......
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