Revert "Fix a legacy TODO (#77454)" (#78584) (#78630)

This reverts commit 5e4e530e934a3a4bd4fff818c3f04193e36a0f7d.
diff --git a/dev/integration_tests/web_e2e_tests/test_driver/text_editing_integration.dart b/dev/integration_tests/web_e2e_tests/test_driver/text_editing_integration.dart
index b0961e1..933ebfc 100644
--- a/dev/integration_tests/web_e2e_tests/test_driver/text_editing_integration.dart
+++ b/dev/integration_tests/web_e2e_tests/test_driver/text_editing_integration.dart
@@ -3,10 +3,8 @@
 // found in the LICENSE file.
 
 // @dart = 2.9
-
 import 'dart:html';
 import 'dart:js_util' as js_util;
-
 import 'package:flutter/gestures.dart';
 import 'package:flutter/services.dart';
 import 'package:flutter_test/flutter_test.dart';
@@ -23,6 +21,9 @@
     app.main();
     await tester.pumpAndSettle();
 
+    // TODO(nurhan): https://github.com/flutter/flutter/issues/51885
+    SystemChannels.textInput.setMockMethodCallHandler(null);
+
     // Focus on a TextFormField.
     final Finder finder = find.byKey(const Key('input'));
     expect(finder, findsOneWidget);
@@ -48,6 +49,9 @@
     app.main();
     await tester.pumpAndSettle();
 
+    // TODO(nurhan): https://github.com/flutter/flutter/issues/51885
+    SystemChannels.textInput.setMockMethodCallHandler(null);
+
     // Focus on a TextFormField.
     final Finder finder = find.byKey(const Key('empty-input'));
     expect(finder, findsOneWidget);
@@ -73,6 +77,9 @@
     app.main();
     await tester.pumpAndSettle();
 
+    // TODO(nurhan): https://github.com/flutter/flutter/issues/51885
+    SystemChannels.textInput.setMockMethodCallHandler(null);
+
     // This text will show no-enter initially. It will have 'enter-pressed'
     // after `onFieldSubmitted` of TextField is triggered.
     final Finder textFinder = find.byKey(const Key('text'));
@@ -106,6 +113,9 @@
     app.main();
     await tester.pumpAndSettle();
 
+    // TODO(nurhan): https://github.com/flutter/flutter/issues/51885
+    SystemChannels.textInput.setMockMethodCallHandler(null);
+
     // Focus on a TextFormField.
     final Finder finder = find.byKey(const Key('input'));
     expect(finder, findsOneWidget);
@@ -138,6 +148,9 @@
     app.main();
     await tester.pumpAndSettle();
 
+    // TODO(nurhan): https://github.com/flutter/flutter/issues/51885
+    SystemChannels.textInput.setMockMethodCallHandler(null);
+
     // Focus on a TextFormField.
     final Finder finder = find.byKey(const Key('input'));
     expect(finder, findsOneWidget);
@@ -185,6 +198,9 @@
     app.main();
     await tester.pumpAndSettle();
 
+    // TODO(nurhan): https://github.com/flutter/flutter/issues/51885
+    SystemChannels.textInput.setMockMethodCallHandler(null);
+
     // Select something from the selectable text.
     final Finder finder = find.byKey(const Key('selectable'));
     expect(finder, findsOneWidget);
diff --git a/packages/flutter_test/lib/src/binding.dart b/packages/flutter_test/lib/src/binding.dart
index b6972f4..fca099e 100644
--- a/packages/flutter_test/lib/src/binding.dart
+++ b/packages/flutter_test/lib/src/binding.dart
@@ -195,15 +195,9 @@
 
   /// Called by the test framework at the beginning of a widget test to
   /// prepare the binding for the next test.
-  ///
-  /// If [registerTestTextInput] returns true when this method is called,
-  /// the [testTextInput] is configured to simulate the keyboard.
   void reset() {
     _restorationManager = null;
     resetGestureBinding();
-    testTextInput.reset();
-    if (registerTestTextInput)
-      _testTextInput.register();
   }
 
   @override
@@ -243,8 +237,7 @@
   @protected
   bool get overrideHttpClient => true;
 
-  /// Determines whether the binding automatically registers [testTextInput] as
-  /// a fake keyboard implementation.
+  /// Determines whether the binding automatically registers [testTextInput].
   ///
   /// Unit tests make use of this to mock out text input communication for
   /// widgets. An integration test would set this to false, to test real IME
@@ -252,19 +245,6 @@
   ///
   /// [TestTextInput.isRegistered] reports whether the text input mock is
   /// registered or not.
-  ///
-  /// Some of the properties and methods on [testTextInput] are only valid if
-  /// [registerTestTextInput] returns true when a test starts. If those
-  /// members are accessed when using a binding that sets this flag to false,
-  /// they will throw.
-  ///
-  /// If this property returns true when a test ends, the [testTextInput] is
-  /// unregistered.
-  ///
-  /// This property should not change the value it returns during the lifetime
-  /// of the binding. Changing the value of this property risks very confusing
-  /// behavior as the [TestTextInput] may be inconsistently registered or
-  /// unregistered.
   @protected
   bool get registerTestTextInput => true;
 
@@ -339,6 +319,9 @@
       binding.setupHttpOverrides();
     }
     _testTextInput = TestTextInput(onCleared: _resetFocusedEditable);
+    if (registerTestTextInput) {
+      _testTextInput.register();
+    }
   }
 
   @override
@@ -816,8 +799,6 @@
       // alone so that we don't cause more spurious errors.
       runApp(Container(key: UniqueKey(), child: _postTestMessage)); // Unmount any remaining widgets.
       await pump();
-      if (registerTestTextInput)
-        _testTextInput.unregister();
       invariantTester();
       _verifyAutoUpdateGoldensUnset(autoUpdateGoldensBeforeTest && !isBrowser);
       _verifyReportTestExceptionUnset(reportTestExceptionBeforeTest);
diff --git a/packages/flutter_test/lib/src/test_text_input.dart b/packages/flutter_test/lib/src/test_text_input.dart
index ca8aed5..1ae2be9 100644
--- a/packages/flutter_test/lib/src/test_text_input.dart
+++ b/packages/flutter_test/lib/src/test_text_input.dart
@@ -15,18 +15,6 @@
 ///
 /// Typical app tests will not need to use this class directly.
 ///
-/// The [TestWidgetsFlutterBinding] class registers a [TestTextInput] instance
-/// ([TestWidgetsFlutterBinding.testTextInput]) as a stub keyboard
-/// implementation if its [TestWidgetsFlutterBinding.registerTestTextInput]
-/// property returns true when a test starts, and unregisters it when the test
-/// ends (unless it ends with a failure).
-///
-/// See [register], [unregister], and [isRegistered] for details.
-///
-/// The [updateEditingValue], [enterText], and [receiveAction] methods can be
-/// used even when the [TestTextInput] is not registered. All other methods
-/// will assert if [isRegistered] is false.
-///
 /// See also:
 ///
 /// * [WidgetTester.enterText], which uses this class to simulate keyboard input.
@@ -49,43 +37,37 @@
   /// The messenger which sends the bytes for this channel, not null.
   BinaryMessenger get _binaryMessenger => ServicesBinding.instance!.defaultBinaryMessenger;
 
+  /// Resets any internal state of this object and calls [register].
+  ///
+  /// This method is invoked by the testing framework between tests. It should
+  /// not ordinarily be called by tests directly.
+  void resetAndRegister() {
+    log.clear();
+    editingState = null;
+    setClientArgs = null;
+    _client = 0;
+    _isVisible = false;
+    register();
+  }
+  /// Installs this object as a mock handler for [SystemChannels.textInput].
+  void register() => SystemChannels.textInput.setMockMethodCallHandler(_handleTextInputCall);
+
+  /// Removes this object as a mock handler for [SystemChannels.textInput].
+  ///
+  /// After calling this method, the channel will exchange messages with the
+  /// Flutter engine. Use this with [FlutterDriver] tests that need to display
+  /// on-screen keyboard provided by the operating system.
+  void unregister() => SystemChannels.textInput.setMockMethodCallHandler(null);
+
   /// Log for method calls.
   ///
   /// For all registered channels, handled calls are added to the list. Can
   /// be cleaned using `log.clear()`.
   final List<MethodCall> log = <MethodCall>[];
 
-  /// Resets any internal state of this object.
-  ///
-  /// This method is invoked by the testing framework between tests. It should
-  /// not ordinarily be called by tests directly.
-  void reset() {
-    log.clear();
-    editingState = null;
-    setClientArgs = null;
-    _client = 0;
-    _isVisible = false;
-  }
-
-  /// Installs this object as a mock handler for [SystemChannels.textInput].
-  ///
-  /// Called by the binding at the top of a test when
-  /// [TestWidgetsFlutterBinding.registerTestTextInput] is true.
-  void register() => SystemChannels.textInput.setMockMethodCallHandler(_handleTextInputCall);
-
-  /// Removes this object as a mock handler for [SystemChannels.textInput].
-  ///
-  /// After calling this method, the channel will exchange messages with the
-  /// Flutter engine instead of the stub.
-  ///
-  /// Called by the binding at the end of a (successful) test when
-  /// [TestWidgetsFlutterBinding.registerTestTextInput] is true.
-  void unregister() => SystemChannels.textInput.setMockMethodCallHandler(null);
-
   /// Whether this [TestTextInput] is registered with [SystemChannels.textInput].
   ///
-  /// The binding uses the [register] and [unregister] methods to control this
-  /// value when [TestWidgetsFlutterBinding.registerTestTextInput] is true.
+  /// Use [register] and [unregister] methods to control this value.
   bool get isRegistered => SystemChannels.textInput.checkMockMethodCallHandler(_handleTextInputCall);
 
   /// Whether there are any active clients listening to text input.
@@ -96,13 +78,11 @@
 
   int _client = 0;
 
-  /// The last set of arguments supplied to the `TextInput.setClient` and
-  /// `TextInput.updateConfig` methods of this stub implementation.
+  /// Arguments supplied to the TextInput.setClient method call.
   Map<String, dynamic>? setClientArgs;
 
   /// The last set of arguments that [TextInputConnection.setEditingState] sent
-  /// to this stub implementation (i.e. the arguments set to
-  /// `TextInput.setEditingState`).
+  /// to the embedder.
   ///
   /// This is a map representation of a [TextEditingValue] object. For example,
   /// it will have a `text` entry whose value matches the most recent
@@ -138,27 +118,15 @@
   }
 
   /// Whether the onscreen keyboard is visible to the user.
-  ///
-  /// Specifically, this reflects the last call to `TextInput.show` or
-  /// `TextInput.hide` received by the stub implementation.
   bool get isVisible {
     assert(isRegistered);
     return _isVisible;
   }
   bool _isVisible = false;
 
-  /// Simulates the user hiding the onscreen keyboard.
-  ///
-  /// This does nothing but set the internal flag.
-  void hide() {
-    assert(isRegistered);
-    _isVisible = false;
-  }
-
   /// Simulates the user changing the [TextEditingValue] to the given value.
-  ///
-  /// This can be called even if the [TestTextInput] has not been [register]ed.
   void updateEditingValue(TextEditingValue value) {
+    assert(isRegistered);
     // Not using the `expect` function because in the case of a FlutterDriver
     // test this code does not run in a package:test test zone.
     if (_client == 0)
@@ -178,7 +146,6 @@
   /// Simulates the user closing the text input connection.
   ///
   /// For example:
-  ///
   /// - User pressed the home button and sent the application to background.
   /// - User closed the virtual keyboard.
   void closeConnection() {
@@ -200,9 +167,8 @@
   }
 
   /// Simulates the user typing the given text.
-  ///
-  /// This can be called even if the [TestTextInput] has not been [register]ed.
   void enterText(String text) {
+    assert(isRegistered);
     updateEditingValue(TextEditingValue(
       text: text,
     ));
@@ -211,9 +177,8 @@
   /// Simulates the user pressing one of the [TextInputAction] buttons.
   /// Does not check that the [TextInputAction] performed is an acceptable one
   /// based on the `inputAction` [setClientArgs].
-  ///
-  /// This can be called even if the [TestTextInput] has not been [register]ed.
   Future<void> receiveAction(TextInputAction action) async {
+    assert(isRegistered);
     return TestAsyncUtils.guard(() {
       // Not using the `expect` function because in the case of a FlutterDriver
       // test this code does not run in a package:test test zone.
@@ -251,4 +216,10 @@
       return completer.future;
     });
   }
+
+  /// Simulates the user hiding the onscreen keyboard.
+  void hide() {
+    assert(isRegistered);
+    _isVisible = false;
+  }
 }
diff --git a/packages/flutter_test/lib/src/widget_tester.dart b/packages/flutter_test/lib/src/widget_tester.dart
index ae24dbd..ac1801d 100644
--- a/packages/flutter_test/lib/src/widget_tester.dart
+++ b/packages/flutter_test/lib/src/widget_tester.dart
@@ -149,6 +149,7 @@
           () async {
             binding.reset();
             debugResetSemanticsIdCounter();
+            tester.resetTestTextInput();
             Object? memento;
             try {
               memento = await variant.setUp(value);
@@ -1001,14 +1002,19 @@
   ///
   /// Typical app tests will not need to use this value. To add text to widgets
   /// like [TextField] or [TextFormField], call [enterText].
-  ///
-  /// Some of the properties and methods on this value are only valid if the
-  /// binding's [TestWidgetsFlutterBinding.registerTestTextInput] flag is set to
-  /// true as a test is starting (meaning that the keyboard is to be simulated
-  /// by the test framework). If those members are accessed when using a binding
-  /// that sets this flag to false, they will throw.
   TestTextInput get testTextInput => binding.testTextInput;
 
+  /// Ensures that [testTextInput] is registered and [TestTextInput.log] is
+  /// reset.
+  ///
+  /// This is called by the testing framework before test runs, so that if a
+  /// previous test has set its own handler on [SystemChannels.textInput], the
+  /// [testTextInput] regains control and the log is fresh for the new test.
+  /// It should not typically need to be called by tests.
+  void resetTestTextInput() {
+    testTextInput.resetAndRegister();
+  }
+
   /// Give the text input widget specified by [finder] the focus, as if the
   /// onscreen keyboard had appeared.
   ///
diff --git a/packages/flutter_test/test/bindings_test.dart b/packages/flutter_test/test/bindings_test.dart
index bc98524..15e1431 100644
--- a/packages/flutter_test/test/bindings_test.dart
+++ b/packages/flutter_test/test/bindings_test.dart
@@ -11,8 +11,6 @@
 import 'package:test_api/test_api.dart' as test_package;
 
 void main() {
-  final AutomatedTestWidgetsFlutterBinding binding = AutomatedTestWidgetsFlutterBinding();
-
   group(TestViewConfiguration, () {
     test('is initialized with top-level window if one is not provided', () {
       // The code below will throw without the default.
@@ -22,32 +20,15 @@
 
   group(AutomatedTestWidgetsFlutterBinding, () {
     test('allows setting defaultTestTimeout to 5 minutes', () {
+      final AutomatedTestWidgetsFlutterBinding binding = AutomatedTestWidgetsFlutterBinding();
       binding.defaultTestTimeout = const test_package.Timeout(Duration(minutes: 5));
       expect(binding.defaultTestTimeout.duration, const Duration(minutes: 5));
     });
   });
 
-  // The next three tests must run in order -- first using `test`, then `testWidgets`, then `test` again.
-
-  int order = 0;
-
   test('Initializes httpOverrides and testTextInput', () async {
-    assert(order == 0);
-    expect(binding.testTextInput, isNotNull);
-    expect(binding.testTextInput.isRegistered, isFalse);
+    final TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized() as TestWidgetsFlutterBinding;
+    expect(binding.testTextInput.isRegistered, true);
     expect(HttpOverrides.current, isNotNull);
-    order += 1;
-  });
-
-  testWidgets('Registers testTextInput', (WidgetTester tester) async {
-    assert(order == 1);
-    expect(tester.testTextInput.isRegistered, isTrue);
-    order += 1;
-  });
-
-  test('Unregisters testTextInput', () async {
-    assert(order == 2);
-    expect(binding.testTextInput.isRegistered, isFalse);
-    order += 1;
   });
 }