Revert "Fix a legacy TODO (#77454) (#79061)" (#79959)
This reverts commit b070ed3c04caa6e348c068b1fe8396527fc46554.
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/lib/src/services/system_channels.dart b/packages/flutter/lib/src/services/system_channels.dart
index 4ab2b27..43e6bf2 100644
--- a/packages/flutter/lib/src/services/system_channels.dart
+++ b/packages/flutter/lib/src/services/system_channels.dart
@@ -120,11 +120,6 @@
/// they apply, so that stale messages referencing past transactions can be
/// ignored.
///
- /// In debug builds, messages sent with a client ID of -1 are always accepted.
- /// This allows tests to smuggle messages without having to mock the engine's
- /// text handling (for example, allowing the engine to still handle the text
- /// input messages in an integration test).
- ///
/// The methods described below are wrapped in a more convenient form by the
/// [TextInput] and [TextInputConnection] class.
///
@@ -157,15 +152,9 @@
/// is a transaction identifier. Calls for stale transactions should be ignored.
///
/// * `TextInputClient.updateEditingState`: The user has changed the contents
- /// of the text control. The second argument is an object with seven keys,
- /// in the form expected by [TextEditingValue.fromJSON].
- ///
- /// * `TextInputClient.updateEditingStateWithTag`: One or more text controls
- /// were autofilled by the platform's autofill service. The first argument
- /// (the client ID) is ignored, the second argument is a map of tags to
- /// objects in the form expected by [TextEditingValue.fromJSON]. See
- /// [AutofillScope.getAutofillClient] for details on the interpretation of
- /// the tag.
+ /// of the text control. The second argument is a [String] containing a
+ /// JSON-encoded object with seven keys, in the form expected by
+ /// [TextEditingValue.fromJSON].
///
/// * `TextInputClient.performAction`: The user has triggered an action. The
/// second argument is a [String] consisting of the stringification of one
@@ -176,8 +165,7 @@
/// one. The framework should call `TextInput.setClient` and
/// `TextInput.setEditingState` again with its most recent information. If
/// there is no existing state on the framework side, the call should
- /// fizzle. (This call is made without a client ID; indeed, without any
- /// arguments at all.)
+ /// fizzle.
///
/// * `TextInputClient.onConnectionClosed`: The text input connection closed
/// on the platform side. For example the application is moved to
diff --git a/packages/flutter/lib/src/services/text_input.dart b/packages/flutter/lib/src/services/text_input.dart
index 5bd3358..bac572f 100644
--- a/packages/flutter/lib/src/services/text_input.dart
+++ b/packages/flutter/lib/src/services/text_input.dart
@@ -1327,11 +1327,9 @@
final List<dynamic> args = methodCall.arguments as List<dynamic>;
- // The updateEditingStateWithTag request (autofill) can come up even to a
- // text field that doesn't have a connection.
if (method == 'TextInputClient.updateEditingStateWithTag') {
- assert(_currentConnection!._client != null);
final TextInputClient client = _currentConnection!._client;
+ assert(client != null);
final AutofillScope? scope = client.currentAutofillScope;
final Map<String, dynamic> editingValue = args[1] as Map<String, dynamic>;
for (final String tag in editingValue.keys) {
@@ -1345,22 +1343,9 @@
}
final int client = args[0] as int;
- if (client != _currentConnection!._id) {
- // If the client IDs don't match, the incoming message was for a different
- // client.
- bool debugAllowAnyway = false;
- assert(() {
- // In debug builds we allow "-1" as a magical client ID that ignores
- // this verification step so that tests can always get through, even
- // when they are not mocking the engine side of text input.
- if (client == -1)
- debugAllowAnyway = true;
- return true;
- }());
- if (!debugAllowAnyway)
- return;
- }
-
+ // The incoming message was for a different client.
+ if (client != _currentConnection!._id)
+ return;
switch (method) {
case 'TextInputClient.updateEditingState':
_currentConnection!._client.updateEditingValue(TextEditingValue.fromJSON(args[1] as Map<String, dynamic>));
diff --git a/packages/flutter/lib/src/widgets/editable_text.dart b/packages/flutter/lib/src/widgets/editable_text.dart
index 0ba9176..f2bb844 100644
--- a/packages/flutter/lib/src/widgets/editable_text.dart
+++ b/packages/flutter/lib/src/widgets/editable_text.dart
@@ -2111,7 +2111,7 @@
if (_hasFocus) {
_openInputConnection();
} else {
- widget.focusNode.requestFocus(); // This eventually calls _openInputConnection also, see _handleFocusChanged.
+ widget.focusNode.requestFocus();
}
}
diff --git a/packages/flutter_test/lib/src/binding.dart b/packages/flutter_test/lib/src/binding.dart
index 9884ca6..bdd115a 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
@@ -532,20 +515,12 @@
TestTextInput get testTextInput => _testTextInput;
late TestTextInput _testTextInput;
- /// The [State] of the current [EditableText] client of the onscreen keyboard.
- ///
- /// Setting this property to a new value causes the given [EditableTextState]
- /// to focus itself and request the keyboard to establish a
- /// [TextInputConnection].
- ///
- /// Callers must pump an additional frame after setting this property to
- /// complete the focus change.
+ /// The current client of the onscreen keyboard. Callers must pump
+ /// an additional frame after setting this property to complete the
+ /// focus change.
///
/// Instead of setting this directly, consider using
/// [WidgetTester.showKeyboard].
- //
- // TODO(ianh): We should just remove this property and move the call to
- // requestKeyboard to the WidgetTester.showKeyboard method.
EditableTextState? get focusedEditable => _focusedEditable;
EditableTextState? _focusedEditable;
set focusedEditable(EditableTextState? value) {
@@ -824,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 e964f58..80fea76 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 [enterText], [updateEditingValue], [receiveAction], and
-/// [closeConnection] 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,76 +37,58 @@
/// 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>[];
- /// 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);
- int? _client;
-
/// Whether there are any active clients listening to text input.
bool get hasAnyClients {
assert(isRegistered);
- return _client != null && _client! > 0;
+ return _client > 0;
}
- /// The last set of arguments supplied to the `TextInput.setClient` and
- /// `TextInput.updateConfig` methods of this stub implementation.
+ int _client = 0;
+
+ /// 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
/// [TextEditingValue.text] that was sent to the embedder.
Map<String, dynamic>? editingState;
- /// 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;
-
- /// 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();
- _client = null;
- setClientArgs = null;
- editingState = null;
- _isVisible = false;
- }
-
Future<dynamic> _handleTextInputCall(MethodCall methodCall) async {
log.add(methodCall);
switch (methodCall.method) {
@@ -130,7 +100,7 @@
setClientArgs = methodCall.arguments as Map<String, dynamic>;
break;
case 'TextInput.clearClient':
- _client = null;
+ _client = 0;
_isVisible = false;
onCleared?.call();
break;
@@ -146,69 +116,87 @@
}
}
- /// Simulates the user hiding the onscreen keyboard.
- ///
- /// This does nothing but set the internal flag.
- void hide() {
+ /// Whether the onscreen keyboard is visible to the user.
+ bool get isVisible {
assert(isRegistered);
- _isVisible = false;
+ return _isVisible;
}
-
- /// Simulates the user typing the given text.
- ///
- /// Calling this method replaces the content of the connected input field with
- /// `text`, and places the caret at the end of the text.
- ///
- /// This can be called even if the [TestTextInput] has not been [register]ed.
- ///
- /// If this is used to inject text when there is a real IME connection, for
- /// example when using the [integration_test] library, there is a risk that
- /// the real IME will become confused as to the current state of input.
- void enterText(String text) {
- updateEditingValue(TextEditingValue(
- text: text,
- selection: TextSelection.collapsed(offset: text.length),
- ));
- }
+ bool _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.
- ///
- /// If this is used to inject text when there is a real IME connection, for
- /// example when using the [integration_test] library, there is a risk that
- /// the real IME will become confused as to the current state of input.
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)
+ throw TestFailure('Tried to use TestTextInput with no keyboard attached. You must use WidgetTester.showKeyboard() first.');
_binaryMessenger.handlePlatformMessage(
SystemChannels.textInput.name,
SystemChannels.textInput.codec.encodeMethodCall(
MethodCall(
'TextInputClient.updateEditingState',
- <dynamic>[_client ?? -1, value.toJSON()],
+ <dynamic>[_client, value.toJSON()],
),
),
(ByteData? data) { /* response from framework is discarded */ },
);
}
+ /// 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() {
+ 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)
+ throw TestFailure('Tried to use TestTextInput with no keyboard attached. You must use WidgetTester.showKeyboard() first.');
+ _binaryMessenger.handlePlatformMessage(
+ SystemChannels.textInput.name,
+ SystemChannels.textInput.codec.encodeMethodCall(
+ MethodCall(
+ 'TextInputClient.onConnectionClosed',
+ <dynamic>[_client,]
+ ),
+ ),
+ (ByteData? data) { /* response from framework is discarded */ },
+ );
+ }
+
+ /// Simulates the user typing the given text.
+ ///
+ /// Calling this method replaces the content of the connected input field with
+ /// `text`, and places the caret at the end of the text.
+ void enterText(String text) {
+ assert(isRegistered);
+ updateEditingValue(TextEditingValue(
+ text: text,
+ selection: TextSelection.collapsed(offset: text.length),
+ ));
+ }
+
/// 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.
- ///
- /// If this is used to inject an action when there is a real IME connection,
- /// for example when using the [integration_test] library, there is a risk
- /// that the real IME will become confused as to the current state of input.
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.
+ if (_client == 0) {
+ throw TestFailure('Tried to use TestTextInput with no keyboard attached. You must use WidgetTester.showKeyboard() first.');
+ }
+
final Completer<void> completer = Completer<void>();
+
_binaryMessenger.handlePlatformMessage(
SystemChannels.textInput.name,
SystemChannels.textInput.codec.encodeMethodCall(
MethodCall(
'TextInputClient.performAction',
- <dynamic>[_client ?? -1, action.toString()],
+ <dynamic>[_client, action.toString()],
),
),
(ByteData? data) {
@@ -232,28 +220,9 @@
});
}
- /// 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.
- ///
- /// This can be called even if the [TestTextInput] has not been [register]ed.
- ///
- /// If this is used to inject text when there is a real IME connection, for
- /// example when using the [integration_test] library, there is a risk that
- /// the real IME will become confused as to the current state of input.
- void closeConnection() {
- _binaryMessenger.handlePlatformMessage(
- SystemChannels.textInput.name,
- SystemChannels.textInput.codec.encodeMethodCall(
- MethodCall(
- 'TextInputClient.onConnectionClosed',
- <dynamic>[_client ?? -1],
- ),
- ),
- (ByteData? data) { /* response from framework is discarded */ },
- );
+ /// 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 224bea5..e5ca5d9 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.
///
@@ -1029,9 +1035,6 @@
matchRoot: true,
),
);
- // Setting focusedEditable causes the binding to call requestKeyboard()
- // on the EditableTextState, which itself eventually calls TextInput.attach
- // to establish the connection.
binding.focusedEditable = editable;
await pump();
});
@@ -1049,12 +1052,6 @@
///
/// To just give [finder] the focus without entering any text,
/// see [showKeyboard].
- ///
- /// To enter text into other widgets (e.g. a custom widget that maintains a
- /// TextInputConnection the way that a [EditableText] does), first ensure that
- /// that widget has an open connection (e.g. by using [tap] to to focus it),
- /// then call `testTextInput.enterText` directly (see
- /// [TestTextInput.enterText]).
Future<void> enterText(Finder finder, String text) async {
return TestAsyncUtils.guard<void>(() async {
await showKeyboard(finder);
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;
});
}