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;
});
}