@@ -4998,6 +4998,84 @@ void main() {
49984998 );
49994999 });
50005000
5001+ testWidgets ('Send text input state to engine when the input formatter rejects user input' , (WidgetTester tester) async {
5002+ // Regression test for https://github.com/flutter/flutter/issues/67828
5003+ final List <MethodCall > log = < MethodCall > [];
5004+ SystemChannels .textInput.setMockMethodCallHandler ((MethodCall methodCall) async {
5005+ log.add (methodCall);
5006+ });
5007+ final TextInputFormatter formatter = TextInputFormatter .withFunction ((TextEditingValue oldValue, TextEditingValue newValue) {
5008+ return const TextEditingValue (text: 'Flutter is the best!' );
5009+ });
5010+ final TextEditingController controller = TextEditingController ();
5011+
5012+ final FocusNode focusNode = FocusNode (debugLabel: 'EditableText Focus Node' );
5013+ Widget builder () {
5014+ return StatefulBuilder (
5015+ builder: (BuildContext context, StateSetter setter) {
5016+ return MaterialApp (
5017+ home: MediaQuery (
5018+ data: const MediaQueryData (devicePixelRatio: 1.0 ),
5019+ child: Directionality (
5020+ textDirection: TextDirection .ltr,
5021+ child: Center (
5022+ child: Material (
5023+ child: EditableText (
5024+ controller: controller,
5025+ focusNode: focusNode,
5026+ style: textStyle,
5027+ cursorColor: Colors .red,
5028+ backgroundCursorColor: Colors .red,
5029+ keyboardType: TextInputType .multiline,
5030+ inputFormatters: < TextInputFormatter > [
5031+ formatter,
5032+ ],
5033+ onChanged: (String value) { },
5034+ ),
5035+ ),
5036+ ),
5037+ ),
5038+ ),
5039+ );
5040+ },
5041+ );
5042+ }
5043+
5044+ await tester.pumpWidget (builder ());
5045+ await tester.tap (find.byType (EditableText ));
5046+ await tester.showKeyboard (find.byType (EditableText ));
5047+ await tester.pump ();
5048+
5049+ log.clear ();
5050+
5051+ final EditableTextState state = tester.firstState (find.byType (EditableText ));
5052+
5053+ // setEditingState is called when remote value modified by the formatter.
5054+ state.updateEditingValue (const TextEditingValue (
5055+ text: 'I will be modified by the formatter.' ,
5056+ ));
5057+ expect (log.length, 1 );
5058+ expect (log, contains (matchesMethodCall (
5059+ 'TextInput.setEditingState' ,
5060+ args: allOf (
5061+ containsPair ('text' , 'Flutter is the best!' ),
5062+ ),
5063+ )));
5064+
5065+ log.clear ();
5066+
5067+ state.updateEditingValue (const TextEditingValue (
5068+ text: 'I will be modified by the formatter.' ,
5069+ ));
5070+ expect (log.length, 1 );
5071+ expect (log, contains (matchesMethodCall (
5072+ 'TextInput.setEditingState' ,
5073+ args: allOf (
5074+ containsPair ('text' , 'Flutter is the best!' ),
5075+ ),
5076+ )));
5077+ });
5078+
50015079 testWidgets ('autofocus:true on first frame does not throw' , (WidgetTester tester) async {
50025080 final TextEditingController controller = TextEditingController (text: testText);
50035081 controller.selection = const TextSelection (
0 commit comments