1// Copyright 2014 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5// TODO(gspencergoog): Remove this tag once this test's state leaks/test
6// dependencies have been fixed.
7// https://github.com/flutter/flutter/issues/85160
8// Fails with "flutter test --test-randomize-ordering-seed=20210721"
9@Tags(<String>['no-shuffle'])
10library;
11
12import 'package:flutter/foundation.dart';
13import 'package:flutter/material.dart';
14import 'package:flutter/services.dart';
15import 'package:flutter_test/flutter_test.dart';
16
17void main() {
18 testWidgets('enterText works', (WidgetTester tester) async {
19 await tester.pumpWidget(const MaterialApp(home: Material(child: TextField())));
20
21 final EditableTextState state = tester.state(find.byType(EditableText));
22 expect(state.textEditingValue.text, '');
23
24 await tester.enterText(find.byType(EditableText), 'let there be text');
25 expect(state.textEditingValue.text, 'let there be text');
26 expect(state.textEditingValue.selection.isCollapsed, isTrue);
27 expect(state.textEditingValue.selection.baseOffset, 17);
28 });
29
30 testWidgets('receiveAction() forwards exception when exception occurs during action processing', (
31 WidgetTester tester,
32 ) async {
33 // Setup a widget that can receive focus so that we can open the keyboard.
34 const Widget widget = MaterialApp(home: Material(child: TextField()));
35 await tester.pumpWidget(widget);
36
37 // Keyboard must be shown for receiveAction() to function.
38 await tester.showKeyboard(find.byType(TextField));
39
40 // Register a handler for the text input channel that throws an error. This
41 // error should be reported within a PlatformException by TestTextInput.
42 SystemChannels.textInput.setMethodCallHandler((MethodCall call) {
43 throw FlutterError('A fake error occurred during action processing.');
44 });
45
46 await expectLater(
47 () => tester.testTextInput.receiveAction(TextInputAction.done),
48 throwsA(isA<PlatformException>()),
49 );
50 });
51
52 testWidgets('selectors are called on macOS', (WidgetTester tester) async {
53 List<dynamic>? selectorNames;
54 await SystemChannels.textInput.invokeMethod('TextInput.setClient', <dynamic>[
55 1,
56 <String, dynamic>{},
57 ]);
58 await SystemChannels.textInput.invokeMethod('TextInput.show');
59 SystemChannels.textInput.setMethodCallHandler((MethodCall call) async {
60 if (call.method == 'TextInputClient.performSelectors') {
61 selectorNames = (call.arguments as List<dynamic>)[1] as List<dynamic>;
62 }
63 });
64 await tester.sendKeyDownEvent(LogicalKeyboardKey.altLeft);
65 await tester.sendKeyDownEvent(LogicalKeyboardKey.arrowUp);
66 await SystemChannels.textInput.invokeMethod('TextInput.clearClient');
67
68 if (defaultTargetPlatform == TargetPlatform.macOS) {
69 expect(selectorNames, <dynamic>['moveBackward:', 'moveToBeginningOfParagraph:']);
70 } else {
71 expect(selectorNames, isNull);
72 }
73 }, variant: TargetPlatformVariant.all());
74
75 testWidgets('selector is called for ctrl + backspace on macOS', (WidgetTester tester) async {
76 List<dynamic>? selectorNames;
77 await SystemChannels.textInput.invokeMethod('TextInput.setClient', <dynamic>[
78 1,
79 <String, dynamic>{},
80 ]);
81 await SystemChannels.textInput.invokeMethod('TextInput.show');
82 SystemChannels.textInput.setMethodCallHandler((MethodCall call) async {
83 if (call.method == 'TextInputClient.performSelectors') {
84 selectorNames = (call.arguments as List<dynamic>)[1] as List<dynamic>;
85 }
86 });
87 await tester.sendKeyDownEvent(LogicalKeyboardKey.control);
88 await tester.sendKeyDownEvent(LogicalKeyboardKey.backspace);
89 await tester.sendKeyUpEvent(LogicalKeyboardKey.backspace);
90 await tester.sendKeyUpEvent(LogicalKeyboardKey.control);
91 await SystemChannels.textInput.invokeMethod('TextInput.clearClient');
92
93 if (defaultTargetPlatform == TargetPlatform.macOS) {
94 expect(selectorNames, <dynamic>['deleteBackwardByDecomposingPreviousCharacter:']);
95 } else {
96 expect(selectorNames, isNull);
97 }
98 }, variant: TargetPlatformVariant.all());
99}
100