diff --git a/dev/automated_tests/flutter_test/ticker_test.dart b/dev/automated_tests/flutter_test/ticker_test.dart index 6881468b2f..48d53f5500 100644 --- a/dev/automated_tests/flutter_test/ticker_test.dart +++ b/dev/automated_tests/flutter_test/ticker_test.dart @@ -11,6 +11,6 @@ void main() { Ticker((Duration duration) { }).start(); final ByteData? message = const StringCodec().encodeMessage('AppLifecycleState.paused'); - await tester.binding.defaultBinaryMessenger.handlePlatformMessage('flutter/lifecycle', message, (_) {}); + await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage('flutter/lifecycle', message, (_) {}); }); } diff --git a/examples/hello_world/test_driver/smoke_web_engine_test.dart b/examples/hello_world/test_driver/smoke_web_engine_test.dart index b2892225b9..2ca900c064 100644 --- a/examples/hello_world/test_driver/smoke_web_engine_test.dart +++ b/examples/hello_world/test_driver/smoke_web_engine_test.dart @@ -5,7 +5,7 @@ import 'dart:async'; import 'package:flutter_driver/flutter_driver.dart'; -import 'package:test/test.dart'; +import 'package:test/test.dart' hide TypeMatcher, isInstanceOf; import 'package:webdriver/async_io.dart'; /// The following test is used as a simple smoke test for verifying Flutter @@ -33,7 +33,6 @@ void main() { test('enable accessibility', () async { await driver.enableAccessibility(); - // TODO(ianh): this delay violates our style guide. We should instead wait for a triggering event. await Future.delayed(const Duration(seconds: 2)); // Elements with tag "flt-semantics" would show up after enabling diff --git a/packages/flutter/lib/src/foundation/binding.dart b/packages/flutter/lib/src/foundation/binding.dart index 71fe7cd043..97a9237d69 100644 --- a/packages/flutter/lib/src/foundation/binding.dart +++ b/packages/flutter/lib/src/foundation/binding.dart @@ -104,8 +104,8 @@ abstract class BindingBase { /// A number of additional bindings are defined as extensions of /// [BindingBase], e.g., [ServicesBinding], [RendererBinding], and /// [WidgetsBinding]. Each of these bindings define behaviors that interact - /// with a [ui.PlatformDispatcher], e.g., [ServicesBinding] registers - /// listeners with the [ChannelBuffers], and [RendererBinding] + /// with a [ui.PlatformDispatcher], e.g., [ServicesBinding] registers a + /// [ui.PlatformDispatcher.onPlatformMessage] handler, and [RendererBinding] /// registers [ui.PlatformDispatcher.onMetricsChanged], /// [ui.PlatformDispatcher.onTextScaleFactorChanged], /// [ui.PlatformDispatcher.onSemanticsEnabledChanged], and diff --git a/packages/flutter/lib/src/services/binary_messenger.dart b/packages/flutter/lib/src/services/binary_messenger.dart index 1acf6f5cb2..39ac547554 100644 --- a/packages/flutter/lib/src/services/binary_messenger.dart +++ b/packages/flutter/lib/src/services/binary_messenger.dart @@ -2,9 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + import 'dart:typed_data'; import 'dart:ui' as ui; +import 'binding.dart'; + /// A function which takes a platform message and asynchronously returns an encoded response. typedef MessageHandler = Future? Function(ByteData? message); @@ -16,39 +19,12 @@ abstract class BinaryMessenger { /// const constructors so that they can be used in const expressions. const BinaryMessenger(); - /// Queues a message. + /// Calls the handler registered for the given channel. /// - /// The returned future completes immediately. - /// - /// This method adds the provided message to the given channel (named by the - /// `channel` argument) of the [ChannelBuffers] object. This simulates what - /// happens when a plugin on the platform thread (e.g. Kotlin or Swift code) - /// sends a message to the plugin package on the Dart thread. - /// - /// The `data` argument contains the message as encoded bytes. (The format - /// used for the message depends on the channel.) - /// - /// The `callback` argument, if non-null, is eventually invoked with the - /// response that would have been sent to the platform thread. - /// - /// In production code, it is more efficient to call - /// `ServicesBinding.instance.channelBuffers.push` directly. - /// - /// In tests, consider using - /// `tester.binding.defaultBinaryMessenger.handlePlatformMessage` (see - /// [WidgetTester], [TestWidgetsFlutterBinding], [TestDefaultBinaryMessenger], - /// and [TestDefaultBinaryMessenger.handlePlatformMessage] respectively). + /// Typically called by [ServicesBinding] to handle platform messages received + /// from [dart:ui.PlatformDispatcher.onPlatformMessage]. /// /// To register a handler for a given message channel, see [setMessageHandler]. - /// - /// To send a message _to_ a plugin on the platform thread, see [send]. - // TODO(ianh): deprecate this method once cocoon and other customer_tests are migrated: - // @NotYetDeprecated( - // 'Instead of calling this method, use ServicesBinding.instance.channelBuffers.push. ' - // 'In tests, consider using tester.binding.defaultBinaryMessenger.handlePlatformMessage ' - // 'or TestDefaultBinaryMessenger.instance.defaultBinaryMessenger.handlePlatformMessage. ' - // 'This feature was deprecated after v2.1.0-10.0.pre.' - // ) Future handlePlatformMessage(String channel, ByteData? data, ui.PlatformMessageResponseCallback? callback); /// Send a binary message to the platform plugins on the given channel. @@ -67,6 +43,37 @@ abstract class BinaryMessenger { /// The handler's return value, if non-null, is sent as a response, unencoded. void setMessageHandler(String channel, MessageHandler? handler); - // Looking for setMockMessageHandler or checkMockMessageHandler? - // See this shim package: packages/flutter_test/lib/src/deprecated.dart + /// Returns true if the `handler` argument matches the `handler` previously + /// passed to [setMessageHandler]. + /// + /// This method is useful for tests or test harnesses that want to assert the + /// handler for the specified channel has not been altered by a previous test. + /// + /// Passing null for the `handler` returns true if the handler for the + /// `channel` is not set. + bool checkMessageHandler(String channel, MessageHandler? handler); + + /// Set a mock callback for intercepting messages from the [send] method on + /// this class, on the given channel, without decoding them. + /// + /// The given callback will replace the currently registered mock callback for + /// that channel, if any. To remove the mock handler, pass null as the + /// `handler` argument. + /// + /// The handler's return value, if non-null, is used as a response, unencoded. + /// + /// This is intended for testing. Messages intercepted in this manner are not + /// sent to platform plugins. + void setMockMessageHandler(String channel, MessageHandler? handler); + + /// Returns true if the `handler` argument matches the `handler` previously + /// passed to [setMockMessageHandler]. + /// + /// This method is useful for tests or test harnesses that want to assert the + /// mock handler for the specified channel has not been altered by a previous + /// test. + /// + /// Passing null for the `handler` returns true if the handler for the + /// `channel` is not set. + bool checkMockMessageHandler(String channel, MessageHandler? handler); } diff --git a/packages/flutter/lib/src/services/binding.dart b/packages/flutter/lib/src/services/binding.dart index db7bdbb067..65aab975c3 100644 --- a/packages/flutter/lib/src/services/binding.dart +++ b/packages/flutter/lib/src/services/binding.dart @@ -28,6 +28,7 @@ mixin ServicesBinding on BindingBase, SchedulerBinding { _instance = this; _defaultBinaryMessenger = createBinaryMessenger(); _restorationManager = createRestorationManager(); + window.onPlatformMessage = defaultBinaryMessenger.handlePlatformMessage; initLicenses(); SystemChannels.system.setMessageHandler((dynamic message) => handleSystemMessage(message as Object)); SystemChannels.lifecycle.setMessageHandler(_handleLifecycleMessage); @@ -46,28 +47,6 @@ mixin ServicesBinding on BindingBase, SchedulerBinding { BinaryMessenger get defaultBinaryMessenger => _defaultBinaryMessenger; late BinaryMessenger _defaultBinaryMessenger; - /// The low level buffering and dispatch mechanism for messages sent by - /// plugins on the engine side to their corresponding plugin code on - /// the framework side. - /// - /// This exposes the [dart:ui.channelBuffers] object. Bindings can override - /// this getter to intercept calls to the [ChannelBuffers] mechanism (for - /// example, for tests). - /// - /// In production, direct access to this object should not be necessary. - /// Messages are received and dispatched by the [defaultBinaryMessenger]. This - /// object is primarily used to send mock messages in tests, via the - /// [ChannelBuffers.push] method (simulating a plugin sending a message to the - /// framework). - /// - /// See also: - /// - /// * [PlatformDispatcher.sendPlatformMessage], which is used for sending - /// messages to plugins from the framework (the opposite of - /// [channelBuffers]). - /// * [platformDispatcher], the [PlatformDispatcher] singleton. - ui.ChannelBuffers get channelBuffers => ui.channelBuffers; - /// Creates a default [BinaryMessenger] instance that can be used for sending /// platform messages. @protected @@ -75,6 +54,7 @@ mixin ServicesBinding on BindingBase, SchedulerBinding { return const _DefaultBinaryMessenger._(); } + /// Called when the operating system notifies the application of a memory /// pressure situation. /// @@ -257,20 +237,17 @@ mixin ServicesBinding on BindingBase, SchedulerBinding { class _DefaultBinaryMessenger extends BinaryMessenger { const _DefaultBinaryMessenger._(); - @override - Future handlePlatformMessage( - String channel, - ByteData? message, - ui.PlatformMessageResponseCallback? callback, - ) async { - ui.channelBuffers.push(channel, message, (ByteData? data) { - if (callback != null) - callback(data); - }); - } + // Handlers for incoming messages from platform plugins. + // This is static so that this class can have a const constructor. + static final Map _handlers = + {}; - @override - Future send(String channel, ByteData? message) { + // Mock handlers that intercept and respond to outgoing messages. + // This is static so that this class can have a const constructor. + static final Map _mockHandlers = + {}; + + Future _sendPlatformMessage(String channel, ByteData? message) { final Completer completer = Completer(); // ui.PlatformDispatcher.instance is accessed directly instead of using // ServicesBinding.instance.platformDispatcher because this method might be @@ -279,8 +256,6 @@ class _DefaultBinaryMessenger extends BinaryMessenger { // ui.PlatformDispatcher.instance because the PlatformDispatcher may be // dependency injected elsewhere with a different instance. However, static // access at this location seems to be the least bad option. - // TODO(ianh): Use ServicesBinding.instance once we have better diagnostics - // on that getter. ui.PlatformDispatcher.instance.sendPlatformMessage(channel, message, (ByteData? reply) { try { completer.complete(reply); @@ -296,27 +271,70 @@ class _DefaultBinaryMessenger extends BinaryMessenger { return completer.future; } + @override + // TODO(goderbauer): Add pragma (and enable test in + // break_on_framework_exceptions_test.dart) when it works on async methods, + // https://github.com/dart-lang/sdk/issues/45673 + // @pragma('vm:notify-debugger-on-exception') + Future handlePlatformMessage( + String channel, + ByteData? data, + ui.PlatformMessageResponseCallback? callback, + ) async { + ByteData? response; + try { + final MessageHandler? handler = _handlers[channel]; + if (handler != null) { + response = await handler(data); + } else { + ui.channelBuffers.push(channel, data, callback!); + callback = null; + } + } catch (exception, stack) { + FlutterError.reportError(FlutterErrorDetails( + exception: exception, + stack: stack, + library: 'services library', + context: ErrorDescription('during a platform message callback'), + )); + } finally { + if (callback != null) { + callback(response); + } + } + } + + @override + Future? send(String channel, ByteData? message) { + final MessageHandler? handler = _mockHandlers[channel]; + if (handler != null) + return handler(message); + return _sendPlatformMessage(channel, message); + } + @override void setMessageHandler(String channel, MessageHandler? handler) { if (handler == null) { - ui.channelBuffers.clearListener(channel); + _handlers.remove(channel); } else { - ui.channelBuffers.setListener(channel, (ByteData? data, ui.PlatformMessageResponseCallback callback) async { - ByteData? response; - try { - response = await handler(data); - } catch (exception, stack) { - - FlutterError.reportError(FlutterErrorDetails( - exception: exception, - stack: stack, - library: 'services library', - context: ErrorDescription('during a platform message callback'), - )); - } finally { - callback(response); - } + _handlers[channel] = handler; + ui.channelBuffers.drain(channel, (ByteData? data, ui.PlatformMessageResponseCallback callback) async { + await handlePlatformMessage(channel, data, callback); }); } } + + @override + bool checkMessageHandler(String channel, MessageHandler? handler) => _handlers[channel] == handler; + + @override + void setMockMessageHandler(String channel, MessageHandler? handler) { + if (handler == null) + _mockHandlers.remove(channel); + else + _mockHandlers[channel] = handler; + } + + @override + bool checkMockMessageHandler(String channel, MessageHandler? handler) => _mockHandlers[channel] == handler; } diff --git a/packages/flutter/lib/src/services/message_codec.dart b/packages/flutter/lib/src/services/message_codec.dart index ba99134778..c31297203c 100644 --- a/packages/flutter/lib/src/services/message_codec.dart +++ b/packages/flutter/lib/src/services/message_codec.dart @@ -95,6 +95,7 @@ abstract class MethodCodec { ByteData encodeErrorEnvelope({ required String code, String? message, Object? details}); } + /// Thrown to indicate that a platform interaction failed in the platform /// plugin. /// diff --git a/packages/flutter/lib/src/services/platform_channel.dart b/packages/flutter/lib/src/services/platform_channel.dart index c93c445466..c9bad0e210 100644 --- a/packages/flutter/lib/src/services/platform_channel.dart +++ b/packages/flutter/lib/src/services/platform_channel.dart @@ -75,10 +75,31 @@ class BasicMessageChannel { } } - // Looking for setMockMessageHandler? - // See this shim package: packages/flutter_test/lib/src/deprecated.dart + /// Sets a mock callback for intercepting messages sent on this channel. + /// Messages may be null. + /// + /// The given callback will replace the currently registered mock callback for + /// this channel, if any. To remove the mock handler, pass null as the + /// `handler` argument. + /// + /// The handler's return value is used as a message reply. It may be null. + /// + /// This is intended for testing. Messages intercepted in this manner are not + /// sent to platform plugins. + void setMockMessageHandler(Future Function(T? message)? handler) { + if (handler == null) { + binaryMessenger.setMockMessageHandler(name, null); + } else { + binaryMessenger.setMockMessageHandler(name, (ByteData? message) async { + return codec.encodeMessage(await handler(codec.decodeMessage(message))); + }); + } + } } +Expando _methodChannelHandlers = Expando(); +Expando _methodChannelMockHandlers = Expando(); + /// A named channel for communicating with platform plugins using asynchronous /// method calls. /// @@ -353,6 +374,7 @@ class MethodChannel { /// similarly to what happens if no method call handler has been set. /// Any other exception results in an error envelope being sent. void setMethodCallHandler(Future Function(MethodCall call)? handler) { + _methodChannelHandlers[this] = handler; binaryMessenger.setMessageHandler( name, handler == null @@ -361,7 +383,53 @@ class MethodChannel { ); } - Future _handleAsMethodCall(ByteData? message, Future Function(MethodCall call) handler) async { + /// Returns true if the `handler` argument matches the `handler` previously + /// passed to [setMethodCallHandler]. + /// + /// This method is useful for tests or test harnesses that want to assert the + /// handler for the specified channel has not been altered by a previous test. + /// + /// Passing null for the `handler` returns true if the handler for the channel + /// is not set. + bool checkMethodCallHandler(Future Function(MethodCall call)? handler) => _methodChannelHandlers[this] == handler; + + /// Sets a mock callback for intercepting method invocations on this channel. + /// + /// The given callback will replace the currently registered mock callback for + /// this channel, if any. To remove the mock handler, pass null as the + /// `handler` argument. + /// + /// Later calls to [invokeMethod] will result in a successful result, + /// a [PlatformException] or a [MissingPluginException], determined by how + /// the future returned by the mock callback completes. The [codec] of this + /// channel is used to encode and decode values and errors. + /// + /// This is intended for testing. Method calls intercepted in this manner are + /// not sent to platform plugins. + /// + /// The provided `handler` must return a `Future` that completes with the + /// return value of the call. The value will be encoded using + /// [MethodCodec.encodeSuccessEnvelope], to act as if platform plugin had + /// returned that value. + void setMockMethodCallHandler(Future? Function(MethodCall call)? handler) { + _methodChannelMockHandlers[this] = handler; + binaryMessenger.setMockMessageHandler( + name, + handler == null ? null : (ByteData? message) => _handleAsMethodCall(message, handler), + ); + } + + /// Returns true if the `handler` argument matches the `handler` previously + /// passed to [setMockMethodCallHandler]. + /// + /// This method is useful for tests or test harnesses that want to assert the + /// handler for the specified channel has not been altered by a previous test. + /// + /// Passing null for the `handler` returns true if the handler for the channel + /// is not set. + bool checkMockMethodCallHandler(Future Function(MethodCall call)? handler) => _methodChannelMockHandlers[this] == handler; + + Future _handleAsMethodCall(ByteData? message, Future? Function(MethodCall call) handler) async { final MethodCall call = codec.decodeMethodCall(message); try { return codec.encodeSuccessEnvelope(await handler(call)); @@ -377,9 +445,6 @@ class MethodChannel { return codec.encodeErrorEnvelope(code: 'error', message: e.toString(), details: null); } } - - // Looking for setMockMethodCallHandler or checkMethodCallHandler? - // See this shim package: packages/flutter_test/lib/src/deprecated.dart } /// A [MethodChannel] that ignores missing platform plugins. @@ -407,6 +472,7 @@ class OptionalMethodChannel extends MethodChannel { final Map? result = await invokeMethod>(method, arguments); return result?.cast(); } + } /// A named channel for communicating with platform plugins using event streams. diff --git a/packages/flutter/lib/src/services/restoration.dart b/packages/flutter/lib/src/services/restoration.dart index 43956999da..ab42efa24a 100644 --- a/packages/flutter/lib/src/services/restoration.dart +++ b/packages/flutter/lib/src/services/restoration.dart @@ -166,6 +166,7 @@ class RestorationManager extends ChangeNotifier { /// that communications channel, or to set it up differently, as necessary. @protected void initChannels() { + assert(!SystemChannels.restoration.checkMethodCallHandler(_methodHandler)); SystemChannels.restoration.setMethodCallHandler(_methodHandler); } diff --git a/packages/flutter/lib/src/services/text_input.dart b/packages/flutter/lib/src/services/text_input.dart index 0e0c637e49..5bd33587b1 100644 --- a/packages/flutter/lib/src/services/text_input.dart +++ b/packages/flutter/lib/src/services/text_input.dart @@ -1517,7 +1517,7 @@ class TextInput { assert(shouldSave != null); TextInput._instance._channel.invokeMethod( 'TextInput.finishAutofillContext', - shouldSave, + shouldSave , ); } } diff --git a/packages/flutter/lib/src/widgets/editable_text.dart b/packages/flutter/lib/src/widgets/editable_text.dart index 4b1fbdb0ee..e321ab2dde 100644 --- a/packages/flutter/lib/src/widgets/editable_text.dart +++ b/packages/flutter/lib/src/widgets/editable_text.dart @@ -2360,13 +2360,11 @@ class EditableTextState extends State with AutomaticKeepAliveClien void _cursorWaitForStart(Timer timer) { assert(_kCursorBlinkHalfPeriod > _fadeDuration); - assert(!EditableText.debugDeterministicCursor); _cursorTimer?.cancel(); _cursorTimer = Timer.periodic(_kCursorBlinkHalfPeriod, _cursorTick); } void _startCursorTimer() { - assert(_cursorTimer == null); _targetCursorVisibility = true; _cursorBlinkOpacityController.value = 1.0; if (EditableText.debugDeterministicCursor) diff --git a/packages/flutter/test/cupertino/picker_test.dart b/packages/flutter/test/cupertino/picker_test.dart index 24051fcd8c..009d11a489 100644 --- a/packages/flutter/test/cupertino/picker_test.dart +++ b/packages/flutter/test/cupertino/picker_test.dart @@ -202,7 +202,7 @@ void main() { final List selectedItems = []; final List systemCalls = []; - tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async { + SystemChannels.platform.setMockMethodCallHandler((MethodCall methodCall) async { systemCalls.add(methodCall); }); @@ -253,7 +253,7 @@ void main() { final List selectedItems = []; final List systemCalls = []; - tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async { + SystemChannels.platform.setMockMethodCallHandler((MethodCall methodCall) async { systemCalls.add(methodCall); }); diff --git a/packages/flutter/test/cupertino/refresh_test.dart b/packages/flutter/test/cupertino/refresh_test.dart index 25a31031be..d506443dad 100644 --- a/packages/flutter/test/cupertino/refresh_test.dart +++ b/packages/flutter/test/cupertino/refresh_test.dart @@ -173,7 +173,7 @@ void main() { testWidgets('drag past threshold triggers refresh task', (WidgetTester tester) async { final List platformCallLog = []; - tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async { + SystemChannels.platform.setMockMethodCallHandler((MethodCall methodCall) async { platformCallLog.add(methodCall); }); diff --git a/packages/flutter/test/cupertino/scrollbar_test.dart b/packages/flutter/test/cupertino/scrollbar_test.dart index ca6f401a06..18647ab72a 100644 --- a/packages/flutter/test/cupertino/scrollbar_test.dart +++ b/packages/flutter/test/cupertino/scrollbar_test.dart @@ -132,9 +132,9 @@ void main() { await tester.pump(); int hapticFeedbackCalls = 0; - tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async { + SystemChannels.platform.setMockMethodCallHandler((MethodCall methodCall) async { if (methodCall.method == 'HapticFeedback.vibrate') { - hapticFeedbackCalls += 1; + hapticFeedbackCalls++; } }); @@ -680,9 +680,9 @@ void main() { await tester.pump(); int hapticFeedbackCalls = 0; - tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async { + SystemChannels.platform.setMockMethodCallHandler((MethodCall methodCall) async { if (methodCall.method == 'HapticFeedback.vibrate') { - hapticFeedbackCalls += 1; + hapticFeedbackCalls++; } }); diff --git a/packages/flutter/test/cupertino/switch_test.dart b/packages/flutter/test/cupertino/switch_test.dart index 6cd48bfbec..9c475b43be 100644 --- a/packages/flutter/test/cupertino/switch_test.dart +++ b/packages/flutter/test/cupertino/switch_test.dart @@ -47,7 +47,7 @@ void main() { final List log = []; - tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async { + SystemChannels.platform.setMockMethodCallHandler((MethodCall methodCall) async { log.add(methodCall); }); @@ -87,7 +87,7 @@ void main() { bool value2 = false; final List log = []; - tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async { + SystemChannels.platform.setMockMethodCallHandler((MethodCall methodCall) async { log.add(methodCall); }); @@ -154,7 +154,7 @@ void main() { bool value = false; final List log = []; - tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async { + SystemChannels.platform.setMockMethodCallHandler((MethodCall methodCall) async { log.add(methodCall); }); @@ -192,7 +192,7 @@ void main() { bool value = false; final List log = []; - tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async { + SystemChannels.platform.setMockMethodCallHandler((MethodCall methodCall) async { log.add(methodCall); }); diff --git a/packages/flutter/test/cupertino/text_field_test.dart b/packages/flutter/test/cupertino/text_field_test.dart index 93029adabf..b90b3f254d 100644 --- a/packages/flutter/test/cupertino/text_field_test.dart +++ b/packages/flutter/test/cupertino/text_field_test.dart @@ -163,7 +163,7 @@ class PathPointsMatcher extends Matcher { void main() { TestWidgetsFlutterBinding.ensureInitialized(); final MockClipboard mockClipboard = MockClipboard(); - TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, mockClipboard.handleMethodCall); + SystemChannels.platform.setMockMethodCallHandler(mockClipboard.handleMethodCall); // Returns the first RenderEditable. RenderEditable findRenderEditable(WidgetTester tester) { @@ -3227,7 +3227,7 @@ void main() { testWidgets('text field respects keyboardAppearance from theme', (WidgetTester tester) async { final List log = []; - tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.textInput, (MethodCall methodCall) async { + SystemChannels.textInput.setMockMethodCallHandler((MethodCall methodCall) async { log.add(methodCall); }); @@ -3250,7 +3250,7 @@ void main() { testWidgets('text field can override keyboardAppearance from theme', (WidgetTester tester) async { final List log = []; - tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.textInput, (MethodCall methodCall) async { + SystemChannels.textInput.setMockMethodCallHandler((MethodCall methodCall) async { log.add(methodCall); }); diff --git a/packages/flutter/test/cupertino/text_selection_test.dart b/packages/flutter/test/cupertino/text_selection_test.dart index 3f27490005..b67d27ec1d 100644 --- a/packages/flutter/test/cupertino/text_selection_test.dart +++ b/packages/flutter/test/cupertino/text_selection_test.dart @@ -66,7 +66,7 @@ const _LongCupertinoLocalizations longLocalizations = _LongCupertinoLocalization void main() { TestWidgetsFlutterBinding.ensureInitialized(); final MockClipboard mockClipboard = MockClipboard(); - TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, mockClipboard.handleMethodCall); + SystemChannels.platform.setMockMethodCallHandler(mockClipboard.handleMethodCall); // Returns true iff the button is visually enabled. bool appearsEnabled(WidgetTester tester, String text) { diff --git a/packages/flutter/test/foundation/service_extensions_test.dart b/packages/flutter/test/foundation/service_extensions_test.dart index a36f5bc477..dd7ae1a4bd 100644 --- a/packages/flutter/test/foundation/service_extensions_test.dart +++ b/packages/flutter/test/foundation/service_extensions_test.dart @@ -21,8 +21,7 @@ class TestServiceExtensionsBinding extends BindingBase PaintingBinding, SemanticsBinding, RendererBinding, - WidgetsBinding, - TestDefaultBinaryMessengerBinding { + WidgetsBinding { final Map extensions = {}; @@ -468,7 +467,7 @@ void main() { bool completed; completed = false; - TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMessageHandler('flutter/assets', (ByteData? message) async { + ServicesBinding.instance!.defaultBinaryMessenger.setMockMessageHandler('flutter/assets', (ByteData? message) async { expect(utf8.decode(message!.buffer.asUint8List()), 'test'); completed = true; return ByteData(5); // 0x0000000000 @@ -495,7 +494,7 @@ void main() { }); expect(data, isFalse); expect(completed, isTrue); - TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMessageHandler('flutter/assets', null); + ServicesBinding.instance!.defaultBinaryMessenger.setMockMessageHandler('flutter/assets', null); }); test('Service extensions - exit', () async { diff --git a/packages/flutter/test/gestures/gesture_binding_resample_event_on_widget_test.dart b/packages/flutter/test/gestures/gesture_binding_resample_event_on_widget_test.dart index 65d8f7611d..3c3e397706 100644 --- a/packages/flutter/test/gestures/gesture_binding_resample_event_on_widget_test.dart +++ b/packages/flutter/test/gestures/gesture_binding_resample_event_on_widget_test.dart @@ -2,6 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// Logically this file should be part of `gesture_binding_test.dart` but is here +// due to conflict of `flutter_test` and `package:test`. +// See https://github.com/dart-lang/matcher/issues/98 +// TODO(CareF): Consider combine this file back to `gesture_binding_test.dart` +// after #98 is fixed. + import 'dart:ui' as ui; import 'package:clock/clock.dart'; diff --git a/packages/flutter/test/material/checkbox_test.dart b/packages/flutter/test/material/checkbox_test.dart index bb2dd4131a..6422423b0a 100644 --- a/packages/flutter/test/material/checkbox_test.dart +++ b/packages/flutter/test/material/checkbox_test.dart @@ -267,7 +267,7 @@ void main() { testWidgets('has semantic events', (WidgetTester tester) async { dynamic semanticEvent; bool? checkboxValue = false; - tester.binding.defaultBinaryMessenger.setMockDecodedMessageHandler(SystemChannels.accessibility, (dynamic message) async { + SystemChannels.accessibility.setMockMessageHandler((dynamic message) async { semanticEvent = message; }); final SemanticsTester semanticsTester = SemanticsTester(tester); @@ -300,7 +300,7 @@ void main() { }); expect(object.debugSemantics!.getSemanticsData().hasAction(SemanticsAction.tap), true); - tester.binding.defaultBinaryMessenger.setMockDecodedMessageHandler(SystemChannels.accessibility, null); + SystemChannels.accessibility.setMockMessageHandler(null); semanticsTester.dispose(); }); diff --git a/packages/flutter/test/material/feedback_test.dart b/packages/flutter/test/material/feedback_test.dart index 3f80ff838f..06a016c41b 100644 --- a/packages/flutter/test/material/feedback_test.dart +++ b/packages/flutter/test/material/feedback_test.dart @@ -27,14 +27,14 @@ void main () { setUp(() { semanticEvents = >[]; - TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockDecodedMessageHandler(SystemChannels.accessibility, (dynamic message) async { + SystemChannels.accessibility.setMockMessageHandler((dynamic message) async { final Map typedMessage = message as Map; semanticEvents.add(typedMessage.cast()); }); }); tearDown(() { - TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockDecodedMessageHandler(SystemChannels.accessibility, null); + SystemChannels.accessibility.setMockMessageHandler(null); }); testWidgets('forTap', (WidgetTester tester) async { diff --git a/packages/flutter/test/material/feedback_tester.dart b/packages/flutter/test/material/feedback_tester.dart index c65d9949b9..5f1c469f6c 100644 --- a/packages/flutter/test/material/feedback_tester.dart +++ b/packages/flutter/test/material/feedback_tester.dart @@ -3,7 +3,6 @@ // found in the LICENSE file. import 'package:flutter/services.dart'; -import 'package:flutter_test/flutter_test.dart'; /// Tracks how often feedback has been requested since its instantiation. /// @@ -11,7 +10,13 @@ import 'package:flutter_test/flutter_test.dart'; /// cannot be used in combination with other classes that do the same. class FeedbackTester { FeedbackTester() { - TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, _handler); + SystemChannels.platform.setMockMethodCallHandler((MethodCall methodCall) async { + if (methodCall.method == 'HapticFeedback.vibrate') + _hapticCount++; + if (methodCall.method == 'SystemSound.play' && + methodCall.arguments == SystemSoundType.click.toString()) + _clickSoundCount++; + }); } /// Number of times haptic feedback was requested (vibration). @@ -22,17 +27,8 @@ class FeedbackTester { int get clickSoundCount => _clickSoundCount; int _clickSoundCount = 0; - Future _handler(MethodCall methodCall) async { - if (methodCall.method == 'HapticFeedback.vibrate') - _hapticCount++; - if (methodCall.method == 'SystemSound.play' && - methodCall.arguments == SystemSoundType.click.toString()) - _clickSoundCount++; - } - /// Stops tracking. void dispose() { - assert(TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.checkMockMessageHandler(SystemChannels.platform.name, _handler)); - TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, null); + SystemChannels.platform.setMockMethodCallHandler(null); } } diff --git a/packages/flutter/test/material/input_date_picker_form_field_test.dart b/packages/flutter/test/material/input_date_picker_form_field_test.dart index 2e9c3769d1..1ffe81281e 100644 --- a/packages/flutter/test/material/input_date_picker_form_field_test.dart +++ b/packages/flutter/test/material/input_date_picker_form_field_test.dart @@ -241,9 +241,9 @@ void main() { // Fill the clipboard so that the Paste option is available in the text // selection menu. - tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, mockClipboard.handleMethodCall); + SystemChannels.platform.setMockMethodCallHandler(mockClipboard.handleMethodCall); await Clipboard.setData(const ClipboardData(text: 'Clipboard data')); - addTearDown(() => tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, null)); + addTearDown(() => SystemChannels.platform.setMockMethodCallHandler(null)); await tester.pumpWidget(_inputDatePickerField(autofocus: true)); await tester.pumpAndSettle(); diff --git a/packages/flutter/test/material/radio_list_tile_test.dart b/packages/flutter/test/material/radio_list_tile_test.dart index 3c8ee4d493..9841a93b3d 100644 --- a/packages/flutter/test/material/radio_list_tile_test.dart +++ b/packages/flutter/test/material/radio_list_tile_test.dart @@ -539,7 +539,7 @@ void main() { final Key key = UniqueKey(); dynamic semanticEvent; int? radioValue = 2; - tester.binding.defaultBinaryMessenger.setMockDecodedMessageHandler(SystemChannels.accessibility, (dynamic message) async { + SystemChannels.accessibility.setMockMessageHandler((dynamic message) async { semanticEvent = message; }); @@ -570,7 +570,7 @@ void main() { expect(object.debugSemantics!.getSemanticsData().hasAction(SemanticsAction.tap), true); semantics.dispose(); - tester.binding.defaultBinaryMessenger.setMockDecodedMessageHandler(SystemChannels.accessibility, null); + SystemChannels.accessibility.setMockMessageHandler(null); }); testWidgets('RadioListTile can autofocus unless disabled.', (WidgetTester tester) async { diff --git a/packages/flutter/test/material/radio_test.dart b/packages/flutter/test/material/radio_test.dart index e3b0485d99..a62195dba1 100644 --- a/packages/flutter/test/material/radio_test.dart +++ b/packages/flutter/test/material/radio_test.dart @@ -292,7 +292,7 @@ void main() { final Key key = UniqueKey(); dynamic semanticEvent; int? radioValue = 2; - tester.binding.defaultBinaryMessenger.setMockDecodedMessageHandler(SystemChannels.accessibility, (dynamic message) async { + SystemChannels.accessibility.setMockMessageHandler((dynamic message) async { semanticEvent = message; }); @@ -319,7 +319,7 @@ void main() { expect(object.debugSemantics!.getSemanticsData().hasAction(SemanticsAction.tap), true); semantics.dispose(); - tester.binding.defaultBinaryMessenger.setMockDecodedMessageHandler(SystemChannels.accessibility, null); + SystemChannels.accessibility.setMockMessageHandler(null); }); testWidgets('Radio ink ripple is displayed correctly', (WidgetTester tester) async { diff --git a/packages/flutter/test/material/search_test.dart b/packages/flutter/test/material/search_test.dart index 456b61d502..a07a585a19 100644 --- a/packages/flutter/test/material/search_test.dart +++ b/packages/flutter/test/material/search_test.dart @@ -32,12 +32,12 @@ void main() { setUp(() async { // Fill the clipboard so that the Paste option is available in the text // selection menu. - TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, mockClipboard.handleMethodCall); + SystemChannels.platform.setMockMethodCallHandler(mockClipboard.handleMethodCall); await Clipboard.setData(const ClipboardData(text: 'Clipboard data')); }); tearDown(() { - TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, null); + SystemChannels.platform.setMockMethodCallHandler(null); }); testWidgets('Can open and close search', (WidgetTester tester) async { diff --git a/packages/flutter/test/material/switch_test.dart b/packages/flutter/test/material/switch_test.dart index 0f1fd4562b..980b4bf97c 100644 --- a/packages/flutter/test/material/switch_test.dart +++ b/packages/flutter/test/material/switch_test.dart @@ -571,7 +571,7 @@ void main() { testWidgets('switch has semantic events', (WidgetTester tester) async { dynamic semanticEvent; bool value = false; - tester.binding.defaultBinaryMessenger.setMockDecodedMessageHandler(SystemChannels.accessibility, (dynamic message) async { + SystemChannels.accessibility.setMockMessageHandler((dynamic message) async { semanticEvent = message; }); final SemanticsTester semanticsTester = SemanticsTester(tester); @@ -609,13 +609,13 @@ void main() { expect(object.debugSemantics!.getSemanticsData().hasAction(SemanticsAction.tap), true); semanticsTester.dispose(); - tester.binding.defaultBinaryMessenger.setMockDecodedMessageHandler(SystemChannels.accessibility, null); + SystemChannels.accessibility.setMockMessageHandler(null); }); testWidgets('switch sends semantic events from parent if fully merged', (WidgetTester tester) async { dynamic semanticEvent; bool value = false; - tester.binding.defaultBinaryMessenger.setMockDecodedMessageHandler(SystemChannels.accessibility, (dynamic message) async { + SystemChannels.accessibility.setMockMessageHandler((dynamic message) async { semanticEvent = message; }); final SemanticsTester semanticsTester = SemanticsTester(tester); @@ -659,7 +659,7 @@ void main() { expect(object.debugSemantics!.getSemanticsData().hasAction(SemanticsAction.tap), true); semanticsTester.dispose(); - tester.binding.defaultBinaryMessenger.setMockDecodedMessageHandler(SystemChannels.accessibility, null); + SystemChannels.accessibility.setMockMessageHandler(null); }); testWidgets('Switch.adaptive', (WidgetTester tester) async { diff --git a/packages/flutter/test/material/text_field_test.dart b/packages/flutter/test/material/text_field_test.dart index 566f111b6b..2975413115 100644 --- a/packages/flutter/test/material/text_field_test.dart +++ b/packages/flutter/test/material/text_field_test.dart @@ -2,7 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:async'; import 'dart:math' as math; import 'dart:ui' as ui show window, BoxHeightStyle, BoxWidthStyle; @@ -165,20 +164,14 @@ void main() { setUp(() async { debugResetSemanticsIdCounter(); - TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMethodCallHandler( - SystemChannels.platform, - mockClipboard.handleMethodCall, - ); + SystemChannels.platform.setMockMethodCallHandler(mockClipboard.handleMethodCall); // Fill the clipboard so that the Paste option is available in the text // selection menu. await Clipboard.setData(const ClipboardData(text: 'Clipboard data')); }); tearDown(() { - TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMethodCallHandler( - SystemChannels.platform, - null, - ); + SystemChannels.platform.setMockMethodCallHandler(null); }); final Key textFieldKey = UniqueKey(); @@ -344,7 +337,7 @@ void main() { testWidgets('TextField has consistent size', (WidgetTester tester) async { final Key textFieldKey = UniqueKey(); - String? textFieldValue; + late String textFieldValue; await tester.pumpWidget( overlay( @@ -367,16 +360,15 @@ void main() { Future checkText(String testValue) async { return TestAsyncUtils.guard(() async { - expect(textFieldValue, isNull); await tester.enterText(find.byType(TextField), testValue); // Check that the onChanged event handler fired. expect(textFieldValue, equals(testValue)); - textFieldValue = null; await skipPastScrollingAnimation(tester); }); } await checkText(' '); + expect(findTextFieldBox(), equals(inputBox)); expect(inputBox.size, equals(emptyInputSize)); @@ -422,8 +414,6 @@ void main() { text: 'X', selection: TextSelection.collapsed(offset: 1), )); - await tester.idle(); - expect(tester.state(find.byType(EditableText)), editableText); await checkCursorToggle(); }); @@ -4697,8 +4687,8 @@ void main() { ); String clipboardContent = ''; - tester.binding.defaultBinaryMessenger - .setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async { + SystemChannels.platform + .setMockMethodCallHandler((MethodCall methodCall) async { if (methodCall.method == 'Clipboard.setData') clipboardContent = methodCall.arguments['text'] as String; else if (methodCall.method == 'Clipboard.getData') @@ -4770,8 +4760,8 @@ void main() { ); String clipboardContent = ''; - tester.binding.defaultBinaryMessenger - .setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async { + SystemChannels.platform + .setMockMethodCallHandler((MethodCall methodCall) async { if (methodCall.method == 'Clipboard.setData') clipboardContent = methodCall.arguments['text'] as String; else if (methodCall.method == 'Clipboard.getData') @@ -4843,8 +4833,8 @@ void main() { ); const String clipboardContent = 'I love Flutter!'; - tester.binding.defaultBinaryMessenger - .setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async { + SystemChannels.platform + .setMockMethodCallHandler((MethodCall methodCall) async { if (methodCall.method == 'Clipboard.getData') return {'text': clipboardContent}; return null; @@ -4893,8 +4883,8 @@ void main() { maxLines: 3, ); String clipboardContent = ''; - tester.binding.defaultBinaryMessenger - .setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async { + SystemChannels.platform + .setMockMethodCallHandler((MethodCall methodCall) async { if (methodCall.method == 'Clipboard.setData') clipboardContent = methodCall.arguments['text'] as String; else if (methodCall.method == 'Clipboard.getData') @@ -4967,8 +4957,8 @@ void main() { obscureText: true, ); String clipboardContent = ''; - tester.binding.defaultBinaryMessenger - .setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async { + SystemChannels.platform + .setMockMethodCallHandler((MethodCall methodCall) async { if (methodCall.method == 'Clipboard.setData') clipboardContent = methodCall.arguments['text'] as String; else if (methodCall.method == 'Clipboard.getData') @@ -9328,8 +9318,8 @@ void main() { ); bool triedToReadClipboard = false; - tester.binding.defaultBinaryMessenger - .setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async { + SystemChannels.platform + .setMockMethodCallHandler((MethodCall methodCall) async { if (methodCall.method == 'Clipboard.getData') { triedToReadClipboard = true; } diff --git a/packages/flutter/test/material/text_form_field_test.dart b/packages/flutter/test/material/text_form_field_test.dart index 37b486da50..e8e4b4cfc3 100644 --- a/packages/flutter/test/material/text_form_field_test.dart +++ b/packages/flutter/test/material/text_form_field_test.dart @@ -32,7 +32,7 @@ class MockClipboard { void main() { TestWidgetsFlutterBinding.ensureInitialized(); final MockClipboard mockClipboard = MockClipboard(); - TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, mockClipboard.handleMethodCall); + SystemChannels.platform.setMockMethodCallHandler(mockClipboard.handleMethodCall); setUp(() async { // Fill the clipboard so that the Paste option is available in the text diff --git a/packages/flutter/test/material/text_selection_test.dart b/packages/flutter/test/material/text_selection_test.dart index 4fa7537321..91bfb43b0e 100644 --- a/packages/flutter/test/material/text_selection_test.dart +++ b/packages/flutter/test/material/text_selection_test.dart @@ -28,7 +28,7 @@ class MockClipboard { void main() { TestWidgetsFlutterBinding.ensureInitialized(); final MockClipboard mockClipboard = MockClipboard(); - TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, mockClipboard.handleMethodCall); + SystemChannels.platform.setMockMethodCallHandler(mockClipboard.handleMethodCall); setUp(() async { await Clipboard.setData(const ClipboardData(text: 'clipboard data')); diff --git a/packages/flutter/test/material/tooltip_test.dart b/packages/flutter/test/material/tooltip_test.dart index b6944f51e1..671b0815a0 100644 --- a/packages/flutter/test/material/tooltip_test.dart +++ b/packages/flutter/test/material/tooltip_test.dart @@ -1193,7 +1193,7 @@ void main() { testWidgets('has semantic events', (WidgetTester tester) async { final List semanticEvents = []; - tester.binding.defaultBinaryMessenger.setMockDecodedMessageHandler(SystemChannels.accessibility, (dynamic message) async { + SystemChannels.accessibility.setMockMessageHandler((dynamic message) async { semanticEvents.add(message); }); final SemanticsTester semantics = SemanticsTester(tester); @@ -1230,7 +1230,7 @@ void main() { }, ])); semantics.dispose(); - tester.binding.defaultBinaryMessenger.setMockDecodedMessageHandler(SystemChannels.accessibility, null); + SystemChannels.accessibility.setMockMessageHandler(null); }); testWidgets('default Tooltip debugFillProperties', (WidgetTester tester) async { final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder(); diff --git a/packages/flutter/test/material/tooltip_theme_test.dart b/packages/flutter/test/material/tooltip_theme_test.dart index f81d8cc834..e18adf1313 100644 --- a/packages/flutter/test/material/tooltip_theme_test.dart +++ b/packages/flutter/test/material/tooltip_theme_test.dart @@ -1153,7 +1153,7 @@ void main() { testWidgets('has semantic events by default - ThemeData.tooltipTheme', (WidgetTester tester) async { final List semanticEvents = []; - tester.binding.defaultBinaryMessenger.setMockDecodedMessageHandler(SystemChannels.accessibility, (dynamic message) async { + SystemChannels.accessibility.setMockMessageHandler((dynamic message) async { semanticEvents.add(message); }); final SemanticsTester semantics = SemanticsTester(tester); @@ -1191,12 +1191,12 @@ void main() { }, ])); semantics.dispose(); - tester.binding.defaultBinaryMessenger.setMockDecodedMessageHandler(SystemChannels.accessibility, null); + SystemChannels.accessibility.setMockMessageHandler(null); }); testWidgets('has semantic events by default - TooltipTheme', (WidgetTester tester) async { final List semanticEvents = []; - tester.binding.defaultBinaryMessenger.setMockDecodedMessageHandler(SystemChannels.accessibility, (dynamic message) async { + SystemChannels.accessibility.setMockMessageHandler((dynamic message) async { semanticEvents.add(message); }); final SemanticsTester semantics = SemanticsTester(tester); @@ -1236,7 +1236,7 @@ void main() { }, ])); semantics.dispose(); - tester.binding.defaultBinaryMessenger.setMockDecodedMessageHandler(SystemChannels.accessibility, null); + SystemChannels.accessibility.setMockMessageHandler(null); }); testWidgets('default Tooltip debugFillProperties', (WidgetTester tester) async { diff --git a/packages/flutter/test/rendering/first_frame_test.dart b/packages/flutter/test/rendering/first_frame_test.dart index c6fe2c76b2..6b766c9675 100644 --- a/packages/flutter/test/rendering/first_frame_test.dart +++ b/packages/flutter/test/rendering/first_frame_test.dart @@ -12,11 +12,11 @@ import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; void main() { - final TestRenderBinding binding = TestRenderBinding(); test('Flutter dispatches first frame event on the web only', () async { final Completer completer = Completer(); + final TestRenderBinding binding = TestRenderBinding(); const MethodChannel firstFrameChannel = MethodChannel('flutter/service_worker'); - binding.defaultBinaryMessenger.setMockMethodCallHandler(firstFrameChannel, (MethodCall methodCall) async { + firstFrameChannel.setMockMethodCallHandler((MethodCall methodCall) async { completer.complete(); }); @@ -27,10 +27,4 @@ void main() { }, skip: !kIsWeb); } -class TestRenderBinding extends BindingBase - with SchedulerBinding, - ServicesBinding, - GestureBinding, - SemanticsBinding, - RendererBinding, - TestDefaultBinaryMessengerBinding { } +class TestRenderBinding extends BindingBase with SchedulerBinding, ServicesBinding, GestureBinding, SemanticsBinding, RendererBinding {} diff --git a/packages/flutter/test/rendering/mouse_tracker_cursor_test.dart b/packages/flutter/test/rendering/mouse_tracker_cursor_test.dart index 331b2a3624..7e8423f637 100644 --- a/packages/flutter/test/rendering/mouse_tracker_cursor_test.dart +++ b/packages/flutter/test/rendering/mouse_tracker_cursor_test.dart @@ -56,14 +56,14 @@ void main() { setUp(() { _binding.postFrameCallbacks.clear(); - _binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.mouseCursor, (MethodCall call) async { + SystemChannels.mouseCursor.setMockMethodCallHandler((MethodCall call) async { if (_methodCallHandler != null) return _methodCallHandler!(call); }); }); tearDown(() { - _binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.mouseCursor, null); + SystemChannels.mouseCursor.setMockMethodCallHandler(null); }); test('Should work on platforms that does not support mouse cursor', () async { diff --git a/packages/flutter/test/rendering/mouse_tracker_test_utils.dart b/packages/flutter/test/rendering/mouse_tracker_test_utils.dart index c4c09064f0..a5bd1ed94e 100644 --- a/packages/flutter/test/rendering/mouse_tracker_test_utils.dart +++ b/packages/flutter/test/rendering/mouse_tracker_test_utils.dart @@ -9,7 +9,6 @@ import 'package:flutter/gestures.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter/scheduler.dart'; import 'package:flutter/services.dart'; -import 'package:flutter_test/flutter_test.dart' show TestDefaultBinaryMessengerBinding; class _TestHitTester extends RenderBox { _TestHitTester(this.hitTestOverride); @@ -25,7 +24,7 @@ class _TestHitTester extends RenderBox { // A binding used to test MouseTracker, allowing the test to override hit test // searching. class TestMouseTrackerFlutterBinding extends BindingBase - with SchedulerBinding, ServicesBinding, GestureBinding, SemanticsBinding, RendererBinding, TestDefaultBinaryMessengerBinding { + with SchedulerBinding, ServicesBinding, GestureBinding, SemanticsBinding, RendererBinding { @override void initInstances() { super.initInstances(); diff --git a/packages/flutter/test/rendering/rendering_tester.dart b/packages/flutter/test/rendering/rendering_tester.dart index 65ba5ae80d..b6b0dd9508 100644 --- a/packages/flutter/test/rendering/rendering_tester.dart +++ b/packages/flutter/test/rendering/rendering_tester.dart @@ -9,12 +9,12 @@ import 'package:flutter/gestures.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter/scheduler.dart'; import 'package:flutter/services.dart'; -import 'package:flutter_test/flutter_test.dart' show TestDefaultBinaryMessengerBinding, EnginePhase, fail; +import 'package:flutter_test/flutter_test.dart' show EnginePhase, fail; export 'package:flutter/foundation.dart' show FlutterError, FlutterErrorDetails; -export 'package:flutter_test/flutter_test.dart' show TestDefaultBinaryMessengerBinding, EnginePhase; +export 'package:flutter_test/flutter_test.dart' show EnginePhase; -class TestRenderingFlutterBinding extends BindingBase with SchedulerBinding, ServicesBinding, GestureBinding, PaintingBinding, SemanticsBinding, RendererBinding, TestDefaultBinaryMessengerBinding { +class TestRenderingFlutterBinding extends BindingBase with SchedulerBinding, ServicesBinding, GestureBinding, PaintingBinding, SemanticsBinding, RendererBinding { /// Creates a binding for testing rendering library functionality. /// /// If [onErrors] is not null, it is called if [FlutterError] caught any errors diff --git a/packages/flutter/test/semantics/semantics_service_test.dart b/packages/flutter/test/semantics/semantics_service_test.dart index a7ff5e0b1a..b384e0fbf1 100644 --- a/packages/flutter/test/semantics/semantics_service_test.dart +++ b/packages/flutter/test/semantics/semantics_service_test.dart @@ -13,13 +13,12 @@ void main() { test('Semantic announcement', () async { final List> log = >[]; - Future handleMessage(dynamic mockMessage) async { final Map message = mockMessage as Map; log.add(message); } - TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockDecodedMessageHandler(SystemChannels.accessibility, handleMessage); + SystemChannels.accessibility.setMockMessageHandler(handleMessage); await SemanticsService.announce('announcement 1', TextDirection.ltr); await SemanticsService.announce('announcement 2', TextDirection.rtl); diff --git a/packages/flutter/test/services/autofill_test.dart b/packages/flutter/test/services/autofill_test.dart index 5af15da712..428f6c74fe 100644 --- a/packages/flutter/test/services/autofill_test.dart +++ b/packages/flutter/test/services/autofill_test.dart @@ -191,6 +191,15 @@ class FakeTextChannel implements MethodChannel { incoming = handler; } + @override + bool checkMethodCallHandler(Future Function(MethodCall call)? handler) => throw UnimplementedError(); + + @override + void setMockMethodCallHandler(Future? Function(MethodCall call)? handler) => throw UnimplementedError(); + + @override + bool checkMockMethodCallHandler(Future Function(MethodCall call)? handler) => throw UnimplementedError(); + void validateOutgoingMethodCalls(List calls) { expect(outgoingCalls.length, calls.length); bool hasError = false; diff --git a/packages/flutter/test/services/binding_test.dart b/packages/flutter/test/services/binding_test.dart index 576b665ace..0fae7f8ed6 100644 --- a/packages/flutter/test/services/binding_test.dart +++ b/packages/flutter/test/services/binding_test.dart @@ -30,7 +30,7 @@ L2Paragraph2 L2Paragraph3'''; -const String combinedLicenses = ''' +const String licenses = ''' $license1 -------------------------------------------------------------------------------- $license2 @@ -38,22 +38,20 @@ $license2 class TestBinding extends BindingBase with SchedulerBinding, ServicesBinding { @override - TestDefaultBinaryMessenger get defaultBinaryMessenger => super.defaultBinaryMessenger as TestDefaultBinaryMessenger; - - @override - TestDefaultBinaryMessenger createBinaryMessenger() { - return TestDefaultBinaryMessenger(super.createBinaryMessenger()); + BinaryMessenger createBinaryMessenger() { + return super.createBinaryMessenger() + ..setMockMessageHandler('flutter/assets', (ByteData? message) async { + if (const StringCodec().decodeMessage(message) == 'NOTICES') { + return const StringCodec().encodeMessage(licenses); + } + return null; + }); } } void main() { test('Adds rootBundle LICENSES to LicenseRegistry', () async { - TestBinding().defaultBinaryMessenger.setMockMessageHandler('flutter/assets', (ByteData? message) async { - if (const StringCodec().decodeMessage(message) == 'NOTICES') { - return const StringCodec().encodeMessage(combinedLicenses); - } - return null; - }); + TestBinding(); // The test binding registers a mock handler that returns licenses for the LICENSE key final List licenses = await LicenseRegistry.licenses.toList(); diff --git a/packages/flutter/test/services/default_binary_messenger_test.dart b/packages/flutter/test/services/default_binary_messenger_test.dart index 4ce14e82bf..e6a768d486 100644 --- a/packages/flutter/test/services/default_binary_messenger_test.dart +++ b/packages/flutter/test/services/default_binary_messenger_test.dart @@ -2,10 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:async'; import 'dart:convert'; import 'dart:typed_data'; - +import 'dart:ui' as ui; import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; @@ -20,39 +19,36 @@ void main() { } test('default binary messenger calls callback once', () async { - int countInbound = 0; - int countOutbound = 0; + int count = 0; const String channel = 'foo'; - final ByteData bar = _makeByteData('bar'); - final Completer done = Completer(); - ServicesBinding.instance!.channelBuffers.push( + ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage( channel, - bar, + _makeByteData('bar'), (ByteData? message) async { - expect(message, isNull); - countOutbound += 1; - done.complete(); + count += 1; }, ); - expect(countInbound, equals(0)); - expect(countOutbound, equals(0)); - ServicesBinding.instance!.defaultBinaryMessenger.setMessageHandler( - channel, - (ByteData? message) async { - expect(message, bar); - countInbound += 1; - }, - ); - expect(countInbound, equals(0)); - expect(countOutbound, equals(0)); - await done.future; - expect(countInbound, equals(1)); - expect(countOutbound, equals(1)); + expect(count, equals(0)); + await ui.channelBuffers.drain(channel, (ByteData? data, ui.PlatformMessageResponseCallback callback) async { + callback(null); + }); + expect(count, equals(1)); + }); + + test('can check the handler', () { + Future handler(ByteData? call) => Future.value(null); + final BinaryMessenger messenger = ServicesBinding.instance!.defaultBinaryMessenger; + + expect(messenger.checkMessageHandler('test_channel', null), true); + expect(messenger.checkMessageHandler('test_channel', handler), false); + messenger.setMessageHandler('test_channel', handler); + expect(messenger.checkMessageHandler('test_channel', handler), true); + messenger.setMessageHandler('test_channel', null); }); test('can check the mock handler', () { Future handler(ByteData? call) => Future.value(null); - final TestDefaultBinaryMessenger messenger = TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger; + final BinaryMessenger messenger = ServicesBinding.instance!.defaultBinaryMessenger; expect(messenger.checkMockMessageHandler('test_channel', null), true); expect(messenger.checkMockMessageHandler('test_channel', handler), false); diff --git a/packages/flutter/test/services/deferred_component_test.dart b/packages/flutter/test/services/deferred_component_test.dart index 6665f28467..cc40b8e651 100644 --- a/packages/flutter/test/services/deferred_component_test.dart +++ b/packages/flutter/test/services/deferred_component_test.dart @@ -11,7 +11,7 @@ void main() { test('installDeferredComponent test', () async { final List log = []; - TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.deferredComponent, (MethodCall methodCall) async { + SystemChannels.deferredComponent.setMockMethodCallHandler((MethodCall methodCall) async { log.add(methodCall); }); @@ -27,7 +27,7 @@ void main() { test('uninstallDeferredComponent test', () async { final List log = []; - TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.deferredComponent, (MethodCall methodCall) async { + SystemChannels.deferredComponent.setMockMethodCallHandler((MethodCall methodCall) async { log.add(methodCall); }); diff --git a/packages/flutter/test/services/fake_platform_views.dart b/packages/flutter/test/services/fake_platform_views.dart index 7695c4a92c..9efdce71de 100644 --- a/packages/flutter/test/services/fake_platform_views.dart +++ b/packages/flutter/test/services/fake_platform_views.dart @@ -8,7 +8,6 @@ import 'dart:typed_data'; import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; -import 'package:flutter_test/flutter_test.dart'; /// Used in internal testing. class FakePlatformViewController extends PlatformViewController { @@ -123,7 +122,7 @@ class FakeAndroidViewController implements AndroidViewController { class FakeAndroidPlatformViewsController { FakeAndroidPlatformViewsController() { - TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform_views, _onMethodCall); + SystemChannels.platform_views.setMockMethodCallHandler(_onMethodCall); } Iterable get views => _views.values; @@ -302,7 +301,7 @@ class FakeAndroidPlatformViewsController { class FakeIosPlatformViewsController { FakeIosPlatformViewsController() { - TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform_views, _onMethodCall); + SystemChannels.platform_views.setMockMethodCallHandler(_onMethodCall); } Iterable get views => _views.values; @@ -397,7 +396,7 @@ class FakeIosPlatformViewsController { class FakeHtmlPlatformViewsController { FakeHtmlPlatformViewsController() { - TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform_views, _onMethodCall); + SystemChannels.platform_views.setMockMethodCallHandler(_onMethodCall); } Iterable get views => _views.values; diff --git a/packages/flutter/test/services/haptic_feedback_test.dart b/packages/flutter/test/services/haptic_feedback_test.dart index fa4c67e555..6234a97579 100644 --- a/packages/flutter/test/services/haptic_feedback_test.dart +++ b/packages/flutter/test/services/haptic_feedback_test.dart @@ -11,7 +11,7 @@ void main() { test('Haptic feedback control test', () async { final List log = []; - TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async { + SystemChannels.platform.setMockMethodCallHandler((MethodCall methodCall) async { log.add(methodCall); }); @@ -25,7 +25,7 @@ void main() { Future callAndVerifyHapticFunction(Function hapticFunction, String platformMethodArgument) async { final List log = []; - TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async { + SystemChannels.platform.setMockMethodCallHandler((MethodCall methodCall) async { log.add(methodCall); }); diff --git a/packages/flutter/test/services/platform_channel_test.dart b/packages/flutter/test/services/platform_channel_test.dart index 6adc07b65d..7b7f135fda 100644 --- a/packages/flutter/test/services/platform_channel_test.dart +++ b/packages/flutter/test/services/platform_channel_test.dart @@ -12,7 +12,7 @@ void main() { const MessageCodec string = StringCodec(); const BasicMessageChannel channel = BasicMessageChannel('ch', string); test('can send string message and get reply', () async { - TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMessageHandler( + ServicesBinding.instance!.defaultBinaryMessenger.setMockMessageHandler( 'ch', (ByteData? message) async => string.encodeMessage(string.decodeMessage(message)! + ' world'), ); @@ -23,7 +23,7 @@ void main() { test('can receive string message and send reply', () async { channel.setMessageHandler((String? message) async => message! + ' world'); String? reply; - await TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.handlePlatformMessage( + await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage( 'ch', const StringCodec().encodeMessage('hello'), (ByteData? replyBinary) { @@ -40,7 +40,7 @@ void main() { const MethodChannel channel = MethodChannel('ch7', jsonMethod); const OptionalMethodChannel optionalMethodChannel = OptionalMethodChannel('ch8', jsonMethod); test('can invoke method and get result', () async { - TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMessageHandler( + ServicesBinding.instance!.defaultBinaryMessenger.setMockMessageHandler( 'ch7', (ByteData? message) async { final Map methodCall = jsonMessage.decodeMessage(message) as Map; @@ -56,7 +56,7 @@ void main() { }); test('can invoke list method and get result', () async { - TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMessageHandler( + ServicesBinding.instance!.defaultBinaryMessenger.setMockMessageHandler( 'ch7', (ByteData? message) async { final Map methodCall = jsonMessage.decodeMessage(message) as Map; @@ -72,7 +72,7 @@ void main() { }); test('can invoke list method and get null result', () async { - TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMessageHandler( + ServicesBinding.instance!.defaultBinaryMessenger.setMockMessageHandler( 'ch7', (ByteData? message) async { final Map methodCall = jsonMessage.decodeMessage(message) as Map; @@ -87,7 +87,7 @@ void main() { }); test('can invoke map method and get result', () async { - TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMessageHandler( + ServicesBinding.instance!.defaultBinaryMessenger.setMockMessageHandler( 'ch7', (ByteData? message) async { final Map methodCall = jsonMessage.decodeMessage(message) as Map; @@ -103,7 +103,7 @@ void main() { }); test('can invoke map method and get null result', () async { - TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMessageHandler( + ServicesBinding.instance!.defaultBinaryMessenger.setMockMessageHandler( 'ch7', (ByteData? message) async { final Map methodCall = jsonMessage.decodeMessage(message) as Map; @@ -118,7 +118,7 @@ void main() { }); test('can invoke method and get error', () async { - TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMessageHandler( + ServicesBinding.instance!.defaultBinaryMessenger.setMockMessageHandler( 'ch7', (ByteData? message) async { return jsonMessage.encodeMessage([ @@ -141,7 +141,7 @@ void main() { }); test('can invoke unimplemented method', () async { - TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMessageHandler( + ServicesBinding.instance!.defaultBinaryMessenger.setMockMessageHandler( 'ch7', (ByteData? message) async => null, ); @@ -157,7 +157,7 @@ void main() { }); test('can invoke unimplemented method (optional)', () async { - TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMessageHandler( + ServicesBinding.instance!.defaultBinaryMessenger.setMockMessageHandler( 'ch8', (ByteData? message) async => null, ); @@ -169,7 +169,7 @@ void main() { channel.setMethodCallHandler(null); final ByteData call = jsonMethod.encodeMethodCall(const MethodCall('sayHello', 'hello')); ByteData? envelope; - await TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.handlePlatformMessage('ch7', call, (ByteData? result) { + await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage('ch7', call, (ByteData? result) { envelope = result; }); await null; // just in case there's something async happening @@ -179,7 +179,7 @@ void main() { test('can handle method call with no registered plugin (setting after)', () async { final ByteData call = jsonMethod.encodeMethodCall(const MethodCall('sayHello', 'hello')); ByteData? envelope; - await TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.handlePlatformMessage('ch7', call, (ByteData? result) { + await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage('ch7', call, (ByteData? result) { envelope = result; }); channel.setMethodCallHandler(null); @@ -193,7 +193,7 @@ void main() { }); final ByteData call = jsonMethod.encodeMethodCall(const MethodCall('sayHello', 'hello')); ByteData? envelope; - await TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.handlePlatformMessage('ch7', call, (ByteData? result) { + await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage('ch7', call, (ByteData? result) { envelope = result; }); expect(envelope, isNull); @@ -203,7 +203,7 @@ void main() { channel.setMethodCallHandler((MethodCall call) async => '${call.arguments}, world'); final ByteData call = jsonMethod.encodeMethodCall(const MethodCall('sayHello', 'hello')); ByteData? envelope; - await TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.handlePlatformMessage('ch7', call, (ByteData? result) { + await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage('ch7', call, (ByteData? result) { envelope = result; }); expect(jsonMethod.decodeEnvelope(envelope!), equals('hello, world')); @@ -215,7 +215,7 @@ void main() { }); final ByteData call = jsonMethod.encodeMethodCall(const MethodCall('sayHello', 'hello')); ByteData? envelope; - await TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.handlePlatformMessage('ch7', call, (ByteData? result) { + await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage('ch7', call, (ByteData? result) { envelope = result; }); try { @@ -235,7 +235,7 @@ void main() { }); final ByteData call = jsonMethod.encodeMethodCall(const MethodCall('sayHello', 'hello')); ByteData? envelope; - await TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.handlePlatformMessage('ch7', call, (ByteData? result) { + await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage('ch7', call, (ByteData? result) { envelope = result; }); try { @@ -249,14 +249,24 @@ void main() { } }); - test('can check the mock handler', () async { + test('can check the handler', () { Future handler(MethodCall call) => Future.value(null); const MethodChannel channel = MethodChannel('test_handler'); - expect(TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.checkMockMessageHandler(channel.name, null), true); - expect(TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.checkMockMessageHandler(channel.name, handler), false); - TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMethodCallHandler(channel, handler); - expect(TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.checkMockMessageHandler(channel.name, handler), true); + expect(channel.checkMethodCallHandler(null), true); + expect(channel.checkMethodCallHandler(handler), false); + channel.setMethodCallHandler(handler); + expect(channel.checkMethodCallHandler(handler), true); + }); + + test('can check the mock handler', () { + Future handler(MethodCall call) => Future.value(null); + + const MethodChannel channel = MethodChannel('test_handler'); + expect(channel.checkMockMethodCallHandler(null), true); + expect(channel.checkMockMethodCallHandler(handler), false); + channel.setMockMethodCallHandler(handler); + expect(channel.checkMockMethodCallHandler(handler), true); }); }); @@ -265,7 +275,7 @@ void main() { const MethodCodec jsonMethod = JSONMethodCodec(); const EventChannel channel = EventChannel('ch', jsonMethod); void emitEvent(ByteData? event) { - TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.handlePlatformMessage( + ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage( 'ch', event, (ByteData? reply) {}, @@ -273,7 +283,7 @@ void main() { } test('can receive event stream', () async { bool canceled = false; - TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMessageHandler( + ServicesBinding.instance!.defaultBinaryMessenger.setMockMessageHandler( 'ch', (ByteData? message) async { final Map methodCall = jsonMessage.decodeMessage(message) as Map; @@ -298,7 +308,7 @@ void main() { }); test('can receive error event', () async { - TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMessageHandler( + ServicesBinding.instance!.defaultBinaryMessenger.setMockMessageHandler( 'ch', (ByteData? message) async { final Map methodCall = jsonMessage.decodeMessage(message) as Map; diff --git a/packages/flutter/test/services/platform_messages_test.dart b/packages/flutter/test/services/platform_messages_test.dart index 8fd3937f5c..9aa9bf1ed8 100644 --- a/packages/flutter/test/services/platform_messages_test.dart +++ b/packages/flutter/test/services/platform_messages_test.dart @@ -7,23 +7,24 @@ import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; void main() { - TestWidgetsFlutterBinding.ensureInitialized(); - test('Mock binary message handler control test', () async { + // Initialize all bindings because defaultBinaryMessenger.send() needs a window. + TestWidgetsFlutterBinding.ensureInitialized(); + final List log = []; - TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMessageHandler('test1', (ByteData? message) async { + ServicesBinding.instance!.defaultBinaryMessenger.setMockMessageHandler('test1', (ByteData? message) async { log.add(message); return null; }); final ByteData message = ByteData(2)..setUint16(0, 0xABCD); - await TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.send('test1', message); + await ServicesBinding.instance!.defaultBinaryMessenger.send('test1', message); expect(log, equals([message])); log.clear(); - TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMessageHandler('test1', null); - await TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.send('test1', message); + ServicesBinding.instance!.defaultBinaryMessenger.setMockMessageHandler('test1', null); + await ServicesBinding.instance!.defaultBinaryMessenger.send('test1', message); expect(log, isEmpty); }); } diff --git a/packages/flutter/test/services/raw_keyboard_test.dart b/packages/flutter/test/services/raw_keyboard_test.dart index 3bbc185b06..7f65991532 100644 --- a/packages/flutter/test/services/raw_keyboard_test.dart +++ b/packages/flutter/test/services/raw_keyboard_test.dart @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; @@ -29,7 +30,6 @@ void main() { RawKeyboard.instance.removeListener(handleKey); } }); - testWidgets('No character is produced for non-printables', (WidgetTester tester) async { for (final String platform in ['linux', 'android', 'macos', 'fuchsia', 'windows', 'web']) { void handleKey(RawKeyEvent event) { @@ -40,7 +40,6 @@ void main() { RawKeyboard.instance.removeListener(handleKey); } }); - testWidgets('keysPressed is maintained', (WidgetTester tester) async { for (final String platform in ['linux', 'android', 'macos', 'fuchsia', 'windows', 'ios']) { RawKeyboard.instance.clearKeysPressed(); @@ -210,7 +209,7 @@ void main() { // when this event is received, but it's not in keysPressed yet. data['modifiers'] |= RawKeyEventDataMacOs.modifierLeftShift | RawKeyEventDataMacOs.modifierShift; // dispatch the modified data. - await TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.handlePlatformMessage( + await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage( SystemChannels.keyEvent.name, SystemChannels.keyEvent.codec.encodeMessage(data), (ByteData? data) {}, @@ -235,7 +234,7 @@ void main() { // when this event is received, but it's not in keysPressed yet. data['modifiers'] |= RawKeyEventDataMacOs.modifierLeftShift | RawKeyEventDataMacOs.modifierShift; // dispatch the modified data. - await TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.handlePlatformMessage( + await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage( SystemChannels.keyEvent.name, SystemChannels.keyEvent.codec.encodeMessage(data), (ByteData? data) {}, @@ -260,7 +259,7 @@ void main() { // when this event is received, but it's not in keysPressed yet. data['modifiers'] |= RawKeyEventDataWindows.modifierLeftShift | RawKeyEventDataWindows.modifierShift; // dispatch the modified data. - await TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.handlePlatformMessage( + await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage( SystemChannels.keyEvent.name, SystemChannels.keyEvent.codec.encodeMessage(data), (ByteData? data) {}, @@ -285,7 +284,7 @@ void main() { // when this event is received, but it's not in keysPressed yet. data['metaState'] |= RawKeyEventDataAndroid.modifierLeftShift | RawKeyEventDataAndroid.modifierShift; // dispatch the modified data. - await TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.handlePlatformMessage( + await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage( SystemChannels.keyEvent.name, SystemChannels.keyEvent.codec.encodeMessage(data), (ByteData? data) {}, @@ -310,7 +309,7 @@ void main() { // when this event is received, but it's not in keysPressed yet. data['modifiers'] |= RawKeyEventDataFuchsia.modifierLeftShift; // dispatch the modified data. - await TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.handlePlatformMessage( + await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage( SystemChannels.keyEvent.name, SystemChannels.keyEvent.codec.encodeMessage(data), (ByteData? data) {}, @@ -335,7 +334,7 @@ void main() { // when this event is received, but it's not in keysPressed yet. data['modifiers'] |= GLFWKeyHelper.modifierShift; // dispatch the modified data. - await TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.handlePlatformMessage( + await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage( SystemChannels.keyEvent.name, SystemChannels.keyEvent.codec.encodeMessage(data), (ByteData? data) {}, @@ -365,7 +364,7 @@ void main() { isDown: true, )..['metaState'] |= RawKeyEventDataWeb.modifierShift; // Dispatch the modified data. - await TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.handlePlatformMessage( + await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage( SystemChannels.keyEvent.name, SystemChannels.keyEvent.codec.encodeMessage(data), (ByteData? data) {}, @@ -457,7 +456,7 @@ void main() { RawKeyEventDataAndroid.modifierControl | RawKeyEventDataAndroid.modifierMeta; // dispatch the modified data. - await TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.handlePlatformMessage( + await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage( SystemChannels.keyEvent.name, SystemChannels.keyEvent.codec.encodeMessage(data), (ByteData? data) {}, @@ -495,7 +494,7 @@ void main() { RawKeyEventDataMacOs.modifierCommand | RawKeyEventDataMacOs.modifierControl; // dispatch the modified data. - await TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.handlePlatformMessage( + await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage( SystemChannels.keyEvent.name, SystemChannels.keyEvent.codec.encodeMessage(data), (ByteData? data) {}, @@ -571,7 +570,7 @@ void main() { RawKeyEventDataWindows.modifierAlt | RawKeyEventDataWindows.modifierControl; // dispatch the modified data. - await TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.handlePlatformMessage( + await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage( SystemChannels.keyEvent.name, SystemChannels.keyEvent.codec.encodeMessage(data), (ByteData? data) {}, @@ -608,7 +607,7 @@ void main() { GLFWKeyHelper.modifierControl | GLFWKeyHelper.modifierMeta; // dispatch the modified data. - await TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.handlePlatformMessage( + await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage( SystemChannels.keyEvent.name, SystemChannels.keyEvent.codec.encodeMessage(data), (ByteData? data) {}, @@ -646,7 +645,7 @@ void main() { RawKeyEventDataWeb.modifierControl | RawKeyEventDataWeb.modifierMeta; // dispatch the modified data. - await TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.handlePlatformMessage( + await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage( SystemChannels.keyEvent.name, SystemChannels.keyEvent.codec.encodeMessage(data), (ByteData? data) {}, @@ -666,6 +665,12 @@ void main() { }); testWidgets('RawKeyboard asserts if no keys are in keysPressed after receiving a key down event', (WidgetTester tester) async { + FlutterErrorDetails? errorDetails; + final FlutterExceptionHandler? oldHandler = FlutterError.onError; + FlutterError.onError = (FlutterErrorDetails details) { + errorDetails = details; + }; + final Map keyEventMessage; if (kIsWeb) { keyEventMessage = const { @@ -687,15 +692,19 @@ void main() { } try { - await TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.handlePlatformMessage( + await ServicesBinding.instance!.defaultBinaryMessenger + .handlePlatformMessage( SystemChannels.keyEvent.name, SystemChannels.keyEvent.codec.encodeMessage(keyEventMessage), - (ByteData? data) { }, + (ByteData? data) {}, ); - fail('Expected an exception, but did not get one.'); - } on AssertionError catch (error) { - expect(error.toString(), contains('Attempted to send a key down event when no keys are in keysPressed')); + } finally { + FlutterError.onError = oldHandler; } + expect(errorDetails, isNotNull); + expect(errorDetails!.stack, isNotNull); + final String fullErrorMessage = errorDetails.toString().replaceAll('\n', ' '); + expect(fullErrorMessage, contains('Attempted to send a key down event when no keys are in keysPressed')); }); }); @@ -748,7 +757,6 @@ void main() { } } }); - test('modifier keys are recognized when combined', () { for (final int modifier in modifierTests.keys) { if (modifier == RawKeyEventDataAndroid.modifierFunction) { @@ -791,7 +799,6 @@ void main() { } } }); - test('Printable keyboard keys are correctly translated', () { final RawKeyEvent keyAEvent = RawKeyEvent.fromMessage({ 'type': 'keydown', @@ -810,7 +817,6 @@ void main() { expect(data.logicalKey, equals(LogicalKeyboardKey.keyA)); expect(data.keyLabel, equals('a')); }); - test('Control keyboard keys are correctly translated', () { final RawKeyEvent escapeKeyEvent = RawKeyEvent.fromMessage(const { 'type': 'keydown', @@ -827,7 +833,6 @@ void main() { expect(data.logicalKey, equals(LogicalKeyboardKey.escape)); expect(data.keyLabel, isEmpty); }); - test('Modifier keyboard keys are correctly translated', () { final RawKeyEvent shiftLeftKeyEvent = RawKeyEvent.fromMessage(const { 'type': 'keydown', @@ -845,7 +850,6 @@ void main() { expect(data.logicalKey, equals(LogicalKeyboardKey.shiftLeft)); expect(data.keyLabel, isEmpty); }); - test('DPAD keys from a joystick give physical key mappings', () { final RawKeyEvent joystickDpadDown = RawKeyEvent.fromMessage(const { 'type': 'keydown', @@ -863,7 +867,6 @@ void main() { expect(data.logicalKey, equals(LogicalKeyboardKey.arrowDown)); expect(data.keyLabel, isEmpty); }); - test('Arrow keys from a keyboard give correct physical key mappings', () { final RawKeyEvent joystickDpadDown = RawKeyEvent.fromMessage(const { 'type': 'keydown', @@ -880,7 +883,6 @@ void main() { expect(data.logicalKey, equals(LogicalKeyboardKey.arrowDown)); expect(data.keyLabel, isEmpty); }); - test('DPAD center from a game pad gives physical key mappings', () { final RawKeyEvent joystickDpadCenter = RawKeyEvent.fromMessage(const { 'type': 'keydown', @@ -898,7 +900,6 @@ void main() { expect(data.logicalKey, equals(LogicalKeyboardKey.select)); expect(data.keyLabel, isEmpty); }); - test('Device id is read from message', () { final RawKeyEvent joystickDpadCenter = RawKeyEvent.fromMessage(const { 'type': 'keydown', @@ -914,7 +915,6 @@ void main() { final RawKeyEventDataAndroid data = joystickDpadCenter.data as RawKeyEventDataAndroid; expect(data.deviceId, equals(10)); }); - test('Repeat count is passed correctly', () { final RawKeyEvent repeatCountEvent = RawKeyEvent.fromMessage({ 'type': 'keydown', @@ -931,7 +931,6 @@ void main() { final RawKeyEventDataAndroid data = repeatCountEvent.data as RawKeyEventDataAndroid; expect(data.repeatCount, equals(42)); }); - testWidgets('Key events are responded to correctly.', (WidgetTester tester) async { expect(RawKeyboard.instance.keysPressed, isEmpty); // Generate the data for a regular key down event. @@ -941,7 +940,7 @@ void main() { isDown: true, ); Map? message; - await TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.handlePlatformMessage( + await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage( SystemChannels.keyEvent.name, SystemChannels.keyEvent.codec.encodeMessage(data), (ByteData? data) { @@ -964,7 +963,7 @@ void main() { focusNode.requestFocus(); await tester.pump(); - await TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.handlePlatformMessage( + await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage( SystemChannels.keyEvent.name, SystemChannels.keyEvent.codec.encodeMessage(data), (ByteData? data) { @@ -972,7 +971,7 @@ void main() { }, ); expect(message, equals({ 'handled': true })); - tester.binding.defaultBinaryMessenger.setMockMessageHandler(SystemChannels.keyEvent.name, null); + ServicesBinding.instance!.defaultBinaryMessenger.setMockMessageHandler(SystemChannels.keyEvent.name, null); }); }, skip: isBrowser); // This is an Android-specific group. @@ -1020,7 +1019,6 @@ void main() { } } }); - test('modifier keys are recognized when combined', () { for (final int modifier in modifierTests.keys) { if (modifier == RawKeyEventDataFuchsia.modifierCapsLock) { @@ -1054,7 +1052,6 @@ void main() { } } }); - test('Printable keyboard keys are correctly translated', () { final RawKeyEvent keyAEvent = RawKeyEvent.fromMessage({ 'type': 'keydown', @@ -1068,7 +1065,6 @@ void main() { expect(data.logicalKey, equals(LogicalKeyboardKey.keyA)); expect(data.keyLabel, equals('a')); }); - test('Control keyboard keys are correctly translated', () { final RawKeyEvent escapeKeyEvent = RawKeyEvent.fromMessage(const { 'type': 'keydown', @@ -1140,7 +1136,6 @@ void main() { } } }); - test('modifier keys are recognized when combined', () { for (final int modifier in modifierTests.keys) { if (modifier == RawKeyEventDataMacOs.modifierCapsLock) { @@ -1180,7 +1175,6 @@ void main() { } } }); - test('Printable keyboard keys are correctly translated', () { const String unmodifiedCharacter = 'a'; final RawKeyEvent keyAEvent = RawKeyEvent.fromMessage(const { @@ -1196,7 +1190,6 @@ void main() { expect(data.logicalKey, equals(LogicalKeyboardKey.keyA)); expect(data.keyLabel, equals('a')); }); - test('Control keyboard keys are correctly translated', () { final RawKeyEvent escapeKeyEvent = RawKeyEvent.fromMessage(const { 'type': 'keydown', @@ -1288,7 +1281,6 @@ void main() { } } }); - test('modifier keys are recognized when combined', () { for (final int modifier in modifierTests.keys) { if (modifier == RawKeyEventDataIos.modifierCapsLock) { @@ -1328,7 +1320,6 @@ void main() { } } }); - test('Printable keyboard keys are correctly translated', () { const String unmodifiedCharacter = 'a'; final RawKeyEvent keyAEvent = RawKeyEvent.fromMessage(const { @@ -1344,7 +1335,6 @@ void main() { expect(data.logicalKey, equals(LogicalKeyboardKey.keyA)); expect(data.keyLabel, equals('a')); }); - test('Control keyboard keys are correctly translated', () { final RawKeyEvent escapeKeyEvent = RawKeyEvent.fromMessage(const { 'type': 'keydown', @@ -1437,7 +1427,6 @@ void main() { } } }); - test('modifier keys are recognized when combined', () { for (final int modifier in modifierTests.keys) { if (modifier == RawKeyEventDataWindows.modifierCaps) { @@ -1477,7 +1466,6 @@ void main() { } } }); - test('Printable keyboard keys are correctly translated', () { const int unmodifiedCharacter = 97; // ASCII value for 'a'. final RawKeyEvent keyAEvent = RawKeyEvent.fromMessage(const { @@ -1493,7 +1481,6 @@ void main() { expect(data.logicalKey, equals(LogicalKeyboardKey.keyA)); expect(data.keyLabel, equals('a')); }); - test('Control keyboard keys are correctly translated', () { final RawKeyEvent escapeKeyEvent = RawKeyEvent.fromMessage(const { 'type': 'keydown', @@ -1508,7 +1495,6 @@ void main() { expect(data.logicalKey, equals(LogicalKeyboardKey.escape)); expect(data.keyLabel, isEmpty); }); - test('Modifier keyboard keys are correctly translated', () { final RawKeyEvent shiftLeftKeyEvent = RawKeyEvent.fromMessage(const { 'type': 'keydown', @@ -1523,7 +1509,6 @@ void main() { expect(data.logicalKey, equals(LogicalKeyboardKey.shiftLeft)); expect(data.keyLabel, isEmpty); }); - test('Unprintable keyboard keys are correctly translated', () { final RawKeyEvent leftArrowKey = RawKeyEvent.fromMessage(const { 'type': 'keydown', @@ -1537,7 +1522,6 @@ void main() { expect(data.physicalKey, equals(PhysicalKeyboardKey.arrowLeft)); expect(data.logicalKey, equals(LogicalKeyboardKey.arrowLeft)); }); - testWidgets('Win32 VK_PROCESSKEY events are skipped', (WidgetTester tester) async { const String platform = 'windows'; bool lastHandled = true; @@ -1636,7 +1620,6 @@ void main() { } } }); - test('modifier keys are recognized when combined', () { for (final int modifier in modifierTests.keys) { if (modifier == GLFWKeyHelper.modifierControl) { @@ -1677,7 +1660,6 @@ void main() { } } }); - test('Printable keyboard keys are correctly translated', () { final RawKeyEvent keyAEvent = RawKeyEvent.fromMessage(const { 'type': 'keydown', @@ -1693,7 +1675,6 @@ void main() { expect(data.logicalKey, equals(LogicalKeyboardKey.keyQ)); expect(data.keyLabel, equals('q')); }); - test('Code points with two Unicode scalar values are allowed', () { final RawKeyEvent keyAEvent = RawKeyEvent.fromMessage(const { 'type': 'keydown', @@ -1742,7 +1723,6 @@ void main() { expect(data.logicalKey, equals(LogicalKeyboardKey.escape)); expect(data.keyLabel, isEmpty); }); - test('Modifier keyboard keys are correctly translated', () { final RawKeyEvent shiftLeftKeyEvent = RawKeyEvent.fromMessage(const { 'type': 'keydown', @@ -1824,7 +1804,6 @@ void main() { } } }); - test('modifier keys are recognized when combined', () { for (final int modifier in modifierTests.keys) { if (modifier == GtkKeyHelper.modifierControl) { @@ -1865,7 +1844,6 @@ void main() { } } }); - test('Printable keyboard keys are correctly translated', () { final RawKeyEvent keyAEvent = RawKeyEvent.fromMessage(const { 'type': 'keydown', @@ -1881,7 +1859,6 @@ void main() { expect(data.logicalKey, equals(LogicalKeyboardKey.keyQ)); expect(data.keyLabel, equals('q')); }); - test('Code points with two Unicode scalar values are allowed', () { final RawKeyEvent keyAEvent = RawKeyEvent.fromMessage(const { 'type': 'keydown', @@ -1930,7 +1907,6 @@ void main() { expect(data.logicalKey, equals(LogicalKeyboardKey.escape)); expect(data.keyLabel, isEmpty); }); - test('Modifier keyboard keys are correctly translated', () { final RawKeyEvent shiftLeftKeyEvent = RawKeyEvent.fromMessage(const { 'type': 'keydown', @@ -1984,7 +1960,6 @@ void main() { } } }); - test('modifier keys are recognized when combined', () { for (final int modifier in modifierTests.keys) { if (modifier == RawKeyEventDataWeb.modifierMeta) { @@ -2017,7 +1992,6 @@ void main() { } } }); - test('Printable keyboard keys are correctly translated', () { final RawKeyEvent keyAEvent = RawKeyEvent.fromMessage(const { 'type': 'keydown', @@ -2031,7 +2005,6 @@ void main() { expect(data.logicalKey, equals(LogicalKeyboardKey.keyA)); expect(data.keyLabel, equals('a')); }); - test('Control keyboard keys are correctly translated', () { final RawKeyEvent escapeKeyEvent = RawKeyEvent.fromMessage(const { 'type': 'keydown', @@ -2044,7 +2017,6 @@ void main() { expect(data.logicalKey, equals(LogicalKeyboardKey.escape)); expect(data.keyLabel, isEmpty); }); - test('Modifier keyboard keys are correctly translated', () { final RawKeyEvent shiftKeyEvent = RawKeyEvent.fromMessage(const { 'type': 'keydown', @@ -2057,7 +2029,6 @@ void main() { expect(data.logicalKey, equals(LogicalKeyboardKey.shiftLeft)); expect(data.keyLabel, isEmpty); }); - test('Arrow keys from a keyboard give correct physical key mappings', () { final RawKeyEvent arrowKeyDown = RawKeyEvent.fromMessage(const { 'type': 'keydown', diff --git a/packages/flutter/test/services/restoration_test.dart b/packages/flutter/test/services/restoration_test.dart index 7a92d4de47..2def380ec8 100644 --- a/packages/flutter/test/services/restoration_test.dart +++ b/packages/flutter/test/services/restoration_test.dart @@ -18,7 +18,7 @@ void main() { testWidgets('root bucket retrieval', (WidgetTester tester) async { final List callsToEngine = []; final Completer> result = Completer>(); - tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.restoration, (MethodCall call) { + SystemChannels.restoration.setMockMethodCallHandler((MethodCall call) { callsToEngine.add(call); return result.future; }); @@ -64,7 +64,7 @@ void main() { testWidgets('root bucket received from engine before retrieval', (WidgetTester tester) async { SystemChannels.restoration.setMethodCallHandler(null); final List callsToEngine = []; - tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.restoration, (MethodCall call) async { + SystemChannels.restoration.setMockMethodCallHandler((MethodCall call) async { callsToEngine.add(call); }); final RestorationManager manager = RestorationManager(); @@ -83,7 +83,7 @@ void main() { SystemChannels.restoration.setMethodCallHandler(null); final List callsToEngine = []; final Completer> result = Completer>(); - tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.restoration, (MethodCall call) { + SystemChannels.restoration.setMockMethodCallHandler((MethodCall call) { callsToEngine.add(call); return result.future; }); @@ -110,7 +110,7 @@ void main() { }); testWidgets('root bucket is properly replaced when new data is available', (WidgetTester tester) async { - tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.restoration, (MethodCall call) async { + SystemChannels.restoration.setMockMethodCallHandler((MethodCall call) async { return _createEncodedRestorationData1(); }); final RestorationManager manager = RestorationManager(); @@ -152,7 +152,7 @@ void main() { testWidgets('returns null as root bucket when restoration is disabled', (WidgetTester tester) async { final List callsToEngine = []; final Completer> result = Completer>(); - tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.restoration, (MethodCall call) { + SystemChannels.restoration.setMockMethodCallHandler((MethodCall call) { callsToEngine.add(call); return result.future; }); @@ -195,7 +195,7 @@ void main() { testWidgets('flushData', (WidgetTester tester) async { final List callsToEngine = []; final Completer> result = Completer>(); - tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.restoration, (MethodCall call) { + SystemChannels.restoration.setMockMethodCallHandler((MethodCall call) { callsToEngine.add(call); return result.future; }); @@ -230,7 +230,7 @@ void main() { testWidgets('isReplacing', (WidgetTester tester) async { final Completer> result = Completer>(); - tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.restoration, (MethodCall call) { + SystemChannels.restoration.setMockMethodCallHandler((MethodCall call) { return result.future; }); diff --git a/packages/flutter/test/services/system_chrome_test.dart b/packages/flutter/test/services/system_chrome_test.dart index 3b196c8ace..5356e4de2b 100644 --- a/packages/flutter/test/services/system_chrome_test.dart +++ b/packages/flutter/test/services/system_chrome_test.dart @@ -7,8 +7,6 @@ import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; void main() { - TestWidgetsFlutterBinding.ensureInitialized(); - testWidgets('SystemChrome overlay style test', (WidgetTester tester) async { // The first call is a cache miss and will queue a microtask SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle.light); @@ -26,7 +24,7 @@ void main() { test('setPreferredOrientations control test', () async { final List log = []; - TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async { + SystemChannels.platform.setMockMethodCallHandler((MethodCall methodCall) async { log.add(methodCall); }); @@ -44,7 +42,7 @@ void main() { test('setApplicationSwitcherDescription control test', () async { final List log = []; - TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async { + SystemChannels.platform.setMockMethodCallHandler((MethodCall methodCall) async { log.add(methodCall); }); @@ -62,7 +60,7 @@ void main() { test('setApplicationSwitcherDescription missing plugin', () async { final List log = []; - TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMessageHandler('flutter/platform', (ByteData? message) async { + ServicesBinding.instance!.defaultBinaryMessenger.setMockMessageHandler('flutter/platform', (ByteData? message) async { log.add(message); }); @@ -76,7 +74,7 @@ void main() { test('setEnabledSystemUIOverlays control test', () async { final List log = []; - TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async { + SystemChannels.platform.setMockMethodCallHandler((MethodCall methodCall) async { log.add(methodCall); }); diff --git a/packages/flutter/test/services/system_navigator_test.dart b/packages/flutter/test/services/system_navigator_test.dart index 251bca6902..bc699856d8 100644 --- a/packages/flutter/test/services/system_navigator_test.dart +++ b/packages/flutter/test/services/system_navigator_test.dart @@ -12,7 +12,7 @@ void main() { test('System navigator control test', () async { final List log = []; - TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async { + SystemChannels.platform.setMockMethodCallHandler((MethodCall methodCall) async { log.add(methodCall); }); diff --git a/packages/flutter/test/services/system_sound_test.dart b/packages/flutter/test/services/system_sound_test.dart index 823d7f083a..20a6d5adb2 100644 --- a/packages/flutter/test/services/system_sound_test.dart +++ b/packages/flutter/test/services/system_sound_test.dart @@ -12,7 +12,7 @@ void main() { test('System sound control test', () async { final List log = []; - TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async { + SystemChannels.platform.setMockMethodCallHandler((MethodCall methodCall) async { log.add(methodCall); }); diff --git a/packages/flutter/test/services/text_input_test.dart b/packages/flutter/test/services/text_input_test.dart index ca3ec02e2e..7d03836808 100644 --- a/packages/flutter/test/services/text_input_test.dart +++ b/packages/flutter/test/services/text_input_test.dart @@ -442,6 +442,16 @@ class FakeTextChannel implements MethodChannel { @override void setMethodCallHandler(Future Function(MethodCall call)? handler) => incoming = handler; + @override + bool checkMethodCallHandler(Future Function(MethodCall call)? handler) => throw UnimplementedError(); + + + @override + void setMockMethodCallHandler(Future? Function(MethodCall call)? handler) => throw UnimplementedError(); + + @override + bool checkMockMethodCallHandler(Future Function(MethodCall call)? handler) => throw UnimplementedError(); + void validateOutgoingMethodCalls(List calls) { expect(outgoingCalls.length, calls.length); bool hasError = false; diff --git a/packages/flutter/test/widgets/draggable_test.dart b/packages/flutter/test/widgets/draggable_test.dart index 9e5bb6bb31..05b5033ff0 100644 --- a/packages/flutter/test/widgets/draggable_test.dart +++ b/packages/flutter/test/widgets/draggable_test.dart @@ -3101,7 +3101,7 @@ Future _testLongPressDraggableHapticFeedback({ required WidgetTester teste bool onDragStartedCalled = false; int hapticFeedbackCalls = 0; - tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async { + SystemChannels.platform.setMockMethodCallHandler((MethodCall methodCall) async { if (methodCall.method == 'HapticFeedback.vibrate') { hapticFeedbackCalls++; } diff --git a/packages/flutter/test/widgets/editable_text_cursor_test.dart b/packages/flutter/test/widgets/editable_text_cursor_test.dart index fd16488a73..09d9089c54 100644 --- a/packages/flutter/test/widgets/editable_text_cursor_test.dart +++ b/packages/flutter/test/widgets/editable_text_cursor_test.dart @@ -75,7 +75,7 @@ void main() { // Populate a fake clipboard. const String clipboardContent = ' '; - tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async { + SystemChannels.platform.setMockMethodCallHandler((MethodCall methodCall) async { if (methodCall.method == 'Clipboard.getData') return const {'text': clipboardContent}; return null; @@ -127,7 +127,7 @@ void main() { // Populate a fake clipboard. const String clipboardContent = ' '; - tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async { + SystemChannels.platform.setMockMethodCallHandler((MethodCall methodCall) async { if (methodCall.method == 'Clipboard.getData') return const {'text': clipboardContent}; return null; @@ -820,7 +820,7 @@ void main() { // Populate a fake clipboard. const String clipboardContent = 'Hello world!'; - tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async { + SystemChannels.platform.setMockMethodCallHandler((MethodCall methodCall) async { if (methodCall.method == 'Clipboard.getData') return const {'text': clipboardContent}; return null; @@ -878,7 +878,7 @@ void main() { // Populate a fake clipboard. const String clipboardContent = 'Hello world!'; - tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async { + SystemChannels.platform.setMockMethodCallHandler((MethodCall methodCall) async { if (methodCall.method == 'Clipboard.getData') return const {'text': clipboardContent}; return null; diff --git a/packages/flutter/test/widgets/editable_text_test.dart b/packages/flutter/test/widgets/editable_text_test.dart index 28018bfe30..8d19d868b9 100644 --- a/packages/flutter/test/widgets/editable_text_test.dart +++ b/packages/flutter/test/widgets/editable_text_test.dart @@ -65,9 +65,9 @@ class MockClipboard { } void main() { + TestWidgetsFlutterBinding.ensureInitialized(); final MockClipboard mockClipboard = MockClipboard(); - (TestWidgetsFlutterBinding.ensureInitialized() as TestWidgetsFlutterBinding) - .defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, mockClipboard.handleMethodCall); + SystemChannels.platform.setMockMethodCallHandler(mockClipboard.handleMethodCall); setUp(() async { debugResetSemanticsIdCounter(); @@ -1985,7 +1985,7 @@ void main() { await tester.pump(); // An extra pump to allow focus request to go through. final List log = []; - tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.textInput, (MethodCall methodCall) async { + SystemChannels.textInput.setMockMethodCallHandler((MethodCall methodCall) async { log.add(methodCall); }); @@ -3176,7 +3176,7 @@ void main() { // Regression test for https://github.com/flutter/flutter/issues/22212. final List log = []; - tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.textInput, (MethodCall methodCall) async { + SystemChannels.textInput.setMockMethodCallHandler((MethodCall methodCall) async { log.add(methodCall); }); @@ -3207,7 +3207,7 @@ void main() { testWidgets('location of widget is sent on show keyboard', (WidgetTester tester) async { final List log = []; - tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.textInput, (MethodCall methodCall) async { + SystemChannels.textInput.setMockMethodCallHandler((MethodCall methodCall) async { log.add(methodCall); }); @@ -3244,7 +3244,7 @@ void main() { testWidgets('transform and size is reset when text connection opens', (WidgetTester tester) async { final List log = []; - tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.textInput, (MethodCall methodCall) async { + SystemChannels.textInput.setMockMethodCallHandler((MethodCall methodCall) async { log.add(methodCall); }); @@ -3332,7 +3332,7 @@ void main() { testWidgets('size and transform are sent when they change', (WidgetTester tester) async { final List log = []; - tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.textInput, (MethodCall methodCall) async { + SystemChannels.textInput.setMockMethodCallHandler((MethodCall methodCall) async { log.add(methodCall); }); @@ -3374,7 +3374,7 @@ void main() { testWidgets('text styling info is sent on show keyboard', (WidgetTester tester) async { final List log = []; - tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.textInput, (MethodCall methodCall) async { + SystemChannels.textInput.setMockMethodCallHandler((MethodCall methodCall) async { log.add(methodCall); }); @@ -3461,7 +3461,7 @@ void main() { await tester.showKeyboard(find.byType(EditableText)); final List log = []; - tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.textInput, (MethodCall methodCall) async { + SystemChannels.textInput.setMockMethodCallHandler((MethodCall methodCall) async { log.add(methodCall); }); setState(() { @@ -3678,7 +3678,7 @@ void main() { // Regression test for https://github.com/flutter/flutter/issues/22212. final List log = []; - tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.textInput, (MethodCall methodCall) async { + SystemChannels.textInput.setMockMethodCallHandler((MethodCall methodCall) async { log.add(methodCall); }); @@ -5639,7 +5639,7 @@ void main() { testWidgets('Synchronous test of local and remote editing values', (WidgetTester tester) async { // Regression test for https://github.com/flutter/flutter/issues/65059 final List log = []; - tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.textInput, (MethodCall methodCall) async { + SystemChannels.textInput.setMockMethodCallHandler((MethodCall methodCall) async { log.add(methodCall); }); final TextInputFormatter formatter = TextInputFormatter.withFunction((TextEditingValue oldValue, TextEditingValue newValue) { @@ -5767,7 +5767,7 @@ void main() { testWidgets('Send text input state to engine when the input formatter rejects user input', (WidgetTester tester) async { // Regression test for https://github.com/flutter/flutter/issues/67828 final List log = []; - tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.textInput, (MethodCall methodCall) async { + SystemChannels.textInput.setMockMethodCallHandler((MethodCall methodCall) async { log.add(methodCall); }); final TextInputFormatter formatter = TextInputFormatter.withFunction((TextEditingValue oldValue, TextEditingValue newValue) { @@ -5846,7 +5846,7 @@ void main() { testWidgets('Repeatedly receiving [TextEditingValue] will not trigger a keyboard request', (WidgetTester tester) async { // Regression test for https://github.com/flutter/flutter/issues/66036 final List log = []; - tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.textInput, (MethodCall methodCall) async { + SystemChannels.textInput.setMockMethodCallHandler((MethodCall methodCall) async { log.add(methodCall); }); final TextEditingController controller = TextEditingController(); @@ -5967,7 +5967,7 @@ void main() { testWidgets('TextEditingController.clear() behavior test', (WidgetTester tester) async { // Regression test for https://github.com/flutter/flutter/issues/66316 final List log = []; - tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.textInput, (MethodCall methodCall) async { + SystemChannels.textInput.setMockMethodCallHandler((MethodCall methodCall) async { log.add(methodCall); }); final TextEditingController controller = TextEditingController(); diff --git a/packages/flutter/test/widgets/modal_barrier_test.dart b/packages/flutter/test/widgets/modal_barrier_test.dart index 1710a4260e..089fb9793d 100644 --- a/packages/flutter/test/widgets/modal_barrier_test.dart +++ b/packages/flutter/test/widgets/modal_barrier_test.dart @@ -165,7 +165,7 @@ void main() { testWidgets('ModalBarrier plays system alert sound when user tries to dismiss it', (WidgetTester tester) async { final List playedSystemSounds = []; try { - tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async { + SystemChannels.platform.setMockMethodCallHandler((MethodCall methodCall) async { if (methodCall.method == 'SystemSound.play') playedSystemSounds.add(methodCall.arguments as String); }); @@ -182,7 +182,7 @@ void main() { await tester.tap(find.text('target'), warnIfMissed: false); await tester.pumpWidget(subject); } finally { - tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, null); + SystemChannels.platform.setMockMethodCallHandler(null); } expect(playedSystemSounds, hasLength(1)); expect(playedSystemSounds[0], SystemSoundType.alert.toString()); diff --git a/packages/flutter/test/widgets/mouse_region_test.dart b/packages/flutter/test/widgets/mouse_region_test.dart index 3b91e9a06c..f74e1a8ada 100644 --- a/packages/flutter/test/widgets/mouse_region_test.dart +++ b/packages/flutter/test/widgets/mouse_region_test.dart @@ -1588,7 +1588,7 @@ void main() { final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse); await gesture.addPointer(location: const Offset(100, 100)); addTearDown(gesture.removePointer); - tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.mouseCursor, (_) async { + SystemChannels.mouseCursor.setMockMethodCallHandler((_) async { logCursors.add('cursor'); }); diff --git a/packages/flutter/test/widgets/platform_view_test.dart b/packages/flutter/test/widgets/platform_view_test.dart index 1755baeb44..1c44cc2c22 100644 --- a/packages/flutter/test/widgets/platform_view_test.dart +++ b/packages/flutter/test/widgets/platform_view_test.dart @@ -1042,7 +1042,7 @@ void main() { await tester.pump(); late int lastPlatformViewTextClient; - tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.textInput, (MethodCall call) { + SystemChannels.textInput.setMockMethodCallHandler((MethodCall call) { if (call.method == 'TextInput.setPlatformViewClient') { lastPlatformViewTextClient = call.arguments as int; } diff --git a/packages/flutter/test/widgets/route_notification_messages_test.dart b/packages/flutter/test/widgets/route_notification_messages_test.dart index d07e582419..566e2eb27d 100644 --- a/packages/flutter/test/widgets/route_notification_messages_test.dart +++ b/packages/flutter/test/widgets/route_notification_messages_test.dart @@ -53,7 +53,7 @@ void main() { final List log = []; - tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.navigation, (MethodCall methodCall) async { + SystemChannels.navigation.setMockMethodCallHandler((MethodCall methodCall) async { log.add(methodCall); }); @@ -105,7 +105,7 @@ void main() { testWidgets('Navigator does not report route name by default', (WidgetTester tester) async { final List log = []; - tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.navigation, (MethodCall methodCall) async { + SystemChannels.navigation.setMockMethodCallHandler((MethodCall methodCall) async { log.add(methodCall); }); @@ -153,7 +153,7 @@ void main() { final List log = []; - tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.navigation, (MethodCall methodCall) async { + SystemChannels.navigation.setMockMethodCallHandler((MethodCall methodCall) async { log.add(methodCall); }); @@ -205,7 +205,7 @@ void main() { testWidgets('Nameless routes should send platform messages', (WidgetTester tester) async { final List log = []; - tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.navigation, (MethodCall methodCall) async { + SystemChannels.navigation.setMockMethodCallHandler((MethodCall methodCall) async { log.add(methodCall); }); @@ -252,7 +252,7 @@ void main() { testWidgets('PlatformRouteInformationProvider reports URL', (WidgetTester tester) async { final List log = []; - tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.navigation, (MethodCall methodCall) async { + SystemChannels.navigation.setMockMethodCallHandler((MethodCall methodCall) async { log.add(methodCall); }); diff --git a/packages/flutter/test/widgets/selectable_text_test.dart b/packages/flutter/test/widgets/selectable_text_test.dart index 1dc285a8d1..f467b2b0df 100644 --- a/packages/flutter/test/widgets/selectable_text_test.dart +++ b/packages/flutter/test/widgets/selectable_text_test.dart @@ -124,7 +124,7 @@ double getOpacity(WidgetTester tester, Finder finder) { void main() { TestWidgetsFlutterBinding.ensureInitialized(); final MockClipboard mockClipboard = MockClipboard(); - TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, mockClipboard.handleMethodCall); + SystemChannels.platform.setMockMethodCallHandler(mockClipboard.handleMethodCall); const String kThreeLines = 'First line of text is\n' @@ -1626,7 +1626,7 @@ void main() { final FocusNode focusNode = FocusNode(); String clipboardContent = ''; - tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async { + SystemChannels.platform.setMockMethodCallHandler((MethodCall methodCall) async { if (methodCall.method == 'Clipboard.setData') clipboardContent = methodCall.arguments['text'] as String; else if (methodCall.method == 'Clipboard.getData') diff --git a/packages/flutter/test/widgets/text_selection_test.dart b/packages/flutter/test/widgets/text_selection_test.dart index 48107e8f0d..8192d15728 100644 --- a/packages/flutter/test/widgets/text_selection_test.dart +++ b/packages/flutter/test/widgets/text_selection_test.dart @@ -19,15 +19,15 @@ class MockClipboard { 'text': null, }; - Future handleMethodCall(MethodCall methodCall) async { + Future handleMethodCall(MethodCall methodCall) async { switch (methodCall.method) { case 'Clipboard.getData': - if (getDataThrows) + if (getDataThrows) { throw Exception(); + } return _clipboardData; case 'Clipboard.setData': _clipboardData = methodCall.arguments; - break; } } } @@ -758,11 +758,11 @@ void main() { group('when Clipboard fails', () { setUp(() { final MockClipboard mockClipboard = MockClipboard(getDataThrows: true); - TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, mockClipboard.handleMethodCall); + SystemChannels.platform.setMockMethodCallHandler(mockClipboard.handleMethodCall); }); tearDown(() { - TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, null); + SystemChannels.platform.setMockMethodCallHandler(null); }); test('Clipboard API failure is gracefully recovered from', () async { @@ -778,11 +778,11 @@ void main() { final MockClipboard mockClipboard = MockClipboard(); setUp(() { - TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, mockClipboard.handleMethodCall); + SystemChannels.platform.setMockMethodCallHandler(mockClipboard.handleMethodCall); }); tearDown(() { - TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, null); + SystemChannels.platform.setMockMethodCallHandler(null); }); test('update sets value based on clipboard contents', () async { diff --git a/packages/flutter/test/widgets/title_test.dart b/packages/flutter/test/widgets/title_test.dart index b3e9a87942..9e7a91eaad 100644 --- a/packages/flutter/test/widgets/title_test.dart +++ b/packages/flutter/test/widgets/title_test.dart @@ -36,7 +36,7 @@ void main() { testWidgets('should not pass "null" to setApplicationSwitcherDescription', (WidgetTester tester) async { final List log = []; - tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async { + SystemChannels.platform.setMockMethodCallHandler((MethodCall methodCall) async { log.add(methodCall); }); diff --git a/packages/flutter_driver/lib/src/extension/extension.dart b/packages/flutter_driver/lib/src/extension/extension.dart index c9caa19281..2150a6e119 100644 --- a/packages/flutter_driver/lib/src/extension/extension.dart +++ b/packages/flutter_driver/lib/src/extension/extension.dart @@ -30,7 +30,7 @@ const String _extensionMethodName = 'driver'; /// eventually completes to a string response. typedef DataHandler = Future Function(String? message); -class _DriverBinding extends BindingBase with SchedulerBinding, ServicesBinding, GestureBinding, PaintingBinding, SemanticsBinding, RendererBinding, WidgetsBinding, TestDefaultBinaryMessengerBinding { +class _DriverBinding extends BindingBase with SchedulerBinding, ServicesBinding, GestureBinding, PaintingBinding, SemanticsBinding, RendererBinding, WidgetsBinding { _DriverBinding(this._handler, this._silenceErrors, this._enableTextEntryEmulation, this.finders, this.commands); final DataHandler? _handler; @@ -51,6 +51,11 @@ class _DriverBinding extends BindingBase with SchedulerBinding, ServicesBinding, registerWebServiceExtension(extension.call); } } + + @override + BinaryMessenger createBinaryMessenger() { + return TestDefaultBinaryMessenger(super.createBinaryMessenger()); + } } /// Enables Flutter Driver VM service extension. @@ -325,11 +330,11 @@ class FlutterDriverExtension with DeserializeFinderFactory, CreateFinderFactory, registerTextInput(); } - for (final FinderExtension finder in finders) { + for(final FinderExtension finder in finders) { _finderExtensions[finder.finderType] = finder; } - for (final CommandExtension command in commands) { + for(final CommandExtension command in commands) { _commandExtensions[command.commandKind] = command; } } @@ -413,7 +418,7 @@ class FlutterDriverExtension with DeserializeFinderFactory, CreateFinderFactory, @override Command deserializeCommand(Map params, DeserializeFinderFactory finderFactory) { final String? kind = params['command']; - if (_commandExtensions.containsKey(kind)) { + if(_commandExtensions.containsKey(kind)) { return _commandExtensions[kind]!.deserialize(params, finderFactory, this); } @@ -429,7 +434,7 @@ class FlutterDriverExtension with DeserializeFinderFactory, CreateFinderFactory, @override Future handleCommand(Command command, WidgetController prober, CreateFinderFactory finderFactory) { final String kind = command.kind; - if (_commandExtensions.containsKey(kind)) { + if(_commandExtensions.containsKey(kind)) { return _commandExtensions[kind]!.call(command, prober, finderFactory, this); } diff --git a/packages/flutter_driver/test/src/real_tests/extension_test.dart b/packages/flutter_driver/test/src/real_tests/extension_test.dart index 24c39834da..6857a2130f 100644 --- a/packages/flutter_driver/test/src/real_tests/extension_test.dart +++ b/packages/flutter_driver/test/src/real_tests/extension_test.dart @@ -279,7 +279,7 @@ void main() { 'waiting for NoPendingPlatformMessages returns until a single method channel call returns', (WidgetTester tester) async { const MethodChannel channel = MethodChannel('helloChannel', JSONMethodCodec()); const MessageCodec jsonMessage = JSONMessageCodec(); - tester.binding.defaultBinaryMessenger.setMockMessageHandler( + ServicesBinding.instance!.defaultBinaryMessenger.setMockMessageHandler( 'helloChannel', (ByteData? message) { return Future.delayed( const Duration(milliseconds: 10), @@ -313,7 +313,7 @@ void main() { const MessageCodec jsonMessage = JSONMessageCodec(); // Configures channel 1 const MethodChannel channel1 = MethodChannel('helloChannel1', JSONMethodCodec()); - tester.binding.defaultBinaryMessenger.setMockMessageHandler( + ServicesBinding.instance!.defaultBinaryMessenger.setMockMessageHandler( 'helloChannel1', (ByteData? message) { return Future.delayed( const Duration(milliseconds: 10), @@ -322,7 +322,7 @@ void main() { // Configures channel 2 const MethodChannel channel2 = MethodChannel('helloChannel2', JSONMethodCodec()); - tester.binding.defaultBinaryMessenger.setMockMessageHandler( + ServicesBinding.instance!.defaultBinaryMessenger.setMockMessageHandler( 'helloChannel2', (ByteData? message) { return Future.delayed( const Duration(milliseconds: 20), @@ -362,7 +362,7 @@ void main() { const MessageCodec jsonMessage = JSONMessageCodec(); // Configures channel 1 const MethodChannel channel1 = MethodChannel('helloChannel1', JSONMethodCodec()); - tester.binding.defaultBinaryMessenger.setMockMessageHandler( + ServicesBinding.instance!.defaultBinaryMessenger.setMockMessageHandler( 'helloChannel1', (ByteData? message) { return Future.delayed( const Duration(milliseconds: 10), @@ -371,7 +371,7 @@ void main() { // Configures channel 2 const MethodChannel channel2 = MethodChannel('helloChannel2', JSONMethodCodec()); - tester.binding.defaultBinaryMessenger.setMockMessageHandler( + ServicesBinding.instance!.defaultBinaryMessenger.setMockMessageHandler( 'helloChannel2', (ByteData? message) { return Future.delayed( const Duration(milliseconds: 20), @@ -413,7 +413,7 @@ void main() { const MessageCodec jsonMessage = JSONMessageCodec(); // Configures channel 1 const MethodChannel channel1 = MethodChannel('helloChannel1', JSONMethodCodec()); - tester.binding.defaultBinaryMessenger.setMockMessageHandler( + ServicesBinding.instance!.defaultBinaryMessenger.setMockMessageHandler( 'helloChannel1', (ByteData? message) { return Future.delayed( const Duration(milliseconds: 20), @@ -422,7 +422,7 @@ void main() { // Configures channel 2 const MethodChannel channel2 = MethodChannel('helloChannel2', JSONMethodCodec()); - tester.binding.defaultBinaryMessenger.setMockMessageHandler( + ServicesBinding.instance!.defaultBinaryMessenger.setMockMessageHandler( 'helloChannel2', (ByteData? message) { return Future.delayed( const Duration(milliseconds: 10), diff --git a/packages/flutter_test/lib/flutter_test.dart b/packages/flutter_test/lib/flutter_test.dart index d7531fff1a..fbeb6f1360 100644 --- a/packages/flutter_test/lib/flutter_test.dart +++ b/packages/flutter_test/lib/flutter_test.dart @@ -61,7 +61,6 @@ export 'src/all_elements.dart'; export 'src/animation_sheet.dart'; export 'src/binding.dart'; export 'src/controller.dart'; -export 'src/deprecated.dart'; export 'src/event_simulation.dart'; export 'src/finders.dart'; export 'src/frame_timing_summarizer.dart'; @@ -74,7 +73,6 @@ export 'src/restoration.dart'; export 'src/stack_manipulation.dart'; export 'src/test_async_utils.dart'; export 'src/test_compat.dart'; -export 'src/test_default_binary_messenger.dart'; export 'src/test_exception_reporter.dart'; export 'src/test_pointer.dart'; export 'src/test_text_input.dart'; diff --git a/packages/flutter_test/lib/src/_binding_io.dart b/packages/flutter_test/lib/src/_binding_io.dart index f09b3e1937..19ec7dbd1f 100644 --- a/packages/flutter_test/lib/src/_binding_io.dart +++ b/packages/flutter_test/lib/src/_binding_io.dart @@ -13,8 +13,8 @@ import 'package:path/path.dart' as path; // ignore: deprecated_member_use import 'package:test_api/test_api.dart' as test_package; + import 'binding.dart'; -import 'deprecated.dart'; /// Ensure the [WidgetsBinding] is initialized. WidgetsBinding ensureInitialized([@visibleForTesting Map? environment]) { diff --git a/packages/flutter_test/lib/src/binding.dart b/packages/flutter_test/lib/src/binding.dart index fce5aa1186..655c0fd395 100644 --- a/packages/flutter_test/lib/src/binding.dart +++ b/packages/flutter_test/lib/src/binding.dart @@ -15,7 +15,8 @@ import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_test/flutter_test.dart' show TestWindow; import 'package:stack_trace/stack_trace.dart' as stack_trace; -import 'package:test_api/test_api.dart' as test_package; // ignore: deprecated_member_use +// ignore: deprecated_member_use +import 'package:test_api/test_api.dart' as test_package; import 'package:vector_math/vector_math_64.dart'; import '_binding_io.dart' if (dart.library.html) '_binding_web.dart' as binding; @@ -24,7 +25,6 @@ import 'platform.dart'; import 'restoration.dart'; import 'stack_manipulation.dart'; import 'test_async_utils.dart'; -import 'test_default_binary_messenger.dart'; import 'test_exception_reporter.dart'; import 'test_text_input.dart'; @@ -79,29 +79,74 @@ enum TestBindingEventSource { const Size _kDefaultTestViewportSize = Size(800.0, 600.0); -/// Overrides the [ServicesBinding]'s binary messenger logic to use -/// [TestDefaultBinaryMessenger]. +/// A [BinaryMessenger] subclass that is used as the default binary messenger +/// under testing environment. /// -/// Test bindings that are used by tests that mock message handlers for plugins -/// should mix in this binding to enable the use of the -/// [TestDefaultBinaryMessenger] APIs. -mixin TestDefaultBinaryMessengerBinding on BindingBase, ServicesBinding { +/// It tracks status of data sent across the Flutter platform barrier, which is +/// useful for testing frameworks to monitor and synchronize against the +/// platform messages. +class TestDefaultBinaryMessenger extends BinaryMessenger { + /// Creates a [TestDefaultBinaryMessenger] instance. + /// + /// The [delegate] instance must not be null. + TestDefaultBinaryMessenger(this.delegate): assert(delegate != null); + + /// The delegate [BinaryMessenger]. + final BinaryMessenger delegate; + + final List> _pendingMessages = >[]; + + /// The number of incomplete/pending calls sent to the platform channels. + int get pendingMessageCount => _pendingMessages.length; + @override - void initInstances() { - super.initInstances(); - _instance = this; + Future? send(String channel, ByteData? message) { + final Future? resultFuture = delegate.send(channel, message); + if (resultFuture != null) { + _pendingMessages.add(resultFuture); + resultFuture + .catchError((Object error) { /* errors are the responsibility of the caller */ }) + .whenComplete(() => _pendingMessages.remove(resultFuture)); + } + return resultFuture; } - /// The current [TestDefaultBinaryMessengerBinding], if one has been created. - static TestDefaultBinaryMessengerBinding? get instance => _instance; - static TestDefaultBinaryMessengerBinding? _instance; + /// Returns a Future that completes after all the platform calls are finished. + /// + /// If a new platform message is sent after this method is called, this new + /// message is not tracked. Use with [pendingMessageCount] to guarantee no + /// pending message calls. + Future get platformMessagesFinished { + return Future.wait(_pendingMessages); + } @override - TestDefaultBinaryMessenger get defaultBinaryMessenger => super.defaultBinaryMessenger as TestDefaultBinaryMessenger; + Future handlePlatformMessage( + String channel, + ByteData? data, + ui.PlatformMessageResponseCallback? callback, + ) { + return delegate.handlePlatformMessage(channel, data, callback); + } @override - TestDefaultBinaryMessenger createBinaryMessenger() { - return TestDefaultBinaryMessenger(super.createBinaryMessenger()); + void setMessageHandler(String channel, MessageHandler? handler) { + delegate.setMessageHandler(channel, handler); + } + + @override + bool checkMessageHandler(String channel, MessageHandler? handler) { + return delegate.checkMessageHandler(channel, handler); + } + + @override + void setMockMessageHandler(String channel, MessageHandler? handler) { + delegate.setMockMessageHandler(channel, handler); + } + + @override + bool checkMockMessageHandler(String channel, MessageHandler? handler) { + return delegate.checkMockMessageHandler(channel, handler); } } @@ -126,8 +171,7 @@ abstract class TestWidgetsFlutterBinding extends BindingBase SemanticsBinding, RendererBinding, PaintingBinding, - WidgetsBinding, - TestDefaultBinaryMessengerBinding { + WidgetsBinding { /// Constructor for [TestWidgetsFlutterBinding]. /// @@ -304,6 +348,11 @@ abstract class TestWidgetsFlutterBinding extends BindingBase // doesn't get generated for tests. } + @override + BinaryMessenger createBinaryMessenger() { + return TestDefaultBinaryMessenger(super.createBinaryMessenger()); + } + /// Whether there is currently a test executing. bool get inTest; diff --git a/packages/flutter_test/lib/src/deprecated.dart b/packages/flutter_test/lib/src/deprecated.dart deleted file mode 100644 index b1e1d63a21..0000000000 --- a/packages/flutter_test/lib/src/deprecated.dart +++ /dev/null @@ -1,109 +0,0 @@ -// Copyright 2014 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'package:flutter/services.dart'; - -import 'binding.dart'; - -// TODO(ianh): Once https://github.com/dart-lang/dartdoc/issues/2033 is fixed, update the hyperlinks marked HYPERLINK below. -// TODO(ianh): Once cocoon and other customer_tests are migrated, deprecate these transitional APIs - -/// Shim to support the obsolete [setMockMessageHandler] and -/// [checkMockMessageHandler] methods on [BinaryMessenger] in tests. -/// -/// The implementations defer to [TestDefaultBinaryMessengerBinding.defaultBinaryMessenger]. -/// -/// Rather than calling [setMockMessageHandler] on the -/// `ServicesBinding.defaultBinaryMessenger`, use -/// `tester.binding.defaultBinaryMessenger.setMockMessageHandler` directly. This -/// more accurately represents the actual method invocation. -extension TestBinaryMessengerExtension on BinaryMessenger { - /// Shim for `TestDefaultBinaryMessenger.setMockMessageHandler`. - // HYPERLINK ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - // TODO(ianh): deprecate this method: @NotYetDeprecated( - // 'Use tester.binding.defaultBinaryMessenger.setMockMessageHandler or ' - // 'TestDefaultBinaryMessenger.instance.defaultBinaryMessenger.setMockMessageHandler instead. ' - // 'This feature was deprecated after v2.1.0-10.0.pre.' - // ) - void setMockMessageHandler(String channel, MessageHandler? handler) { - TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMessageHandler(channel, handler); - } - - /// Shim for `TestDefaultBinaryMessenger.checkMockMessageHandler`. - // HYPERLINK ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - // TODO(ianh): deprecate this method: @NotYetDeprecated( - // 'Use tester.binding.defaultBinaryMessenger.checkMockMessageHandler or ' - // 'TestDefaultBinaryMessenger.instance.defaultBinaryMessenger.checkMockMessageHandler instead.' - // 'This feature was deprecated after v2.1.0-10.0.pre.' - // ) - bool checkMockMessageHandler(String channel, Object? handler) { - return TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.checkMockMessageHandler(channel, handler); - } -} - -/// Shim to support the obsolete [setMockMessageHandler] and -/// [checkMockMessageHandler] methods on [BasicMessageChannel] in tests. -/// -/// The implementations defer to [TestDefaultBinaryMessengerBinding.defaultBinaryMessenger]. -/// -/// Rather than calling [setMockMessageHandler] on the message channel, use -/// `tester.binding.defaultBinaryMessenger.setMockDecodedMessageHandler` -/// directly. This more accurately represents the actual method invocation. -extension TestBasicMessageChannelExtension on BasicMessageChannel { - /// Shim for `TestDefaultBinaryMessenger.setMockDecodedMessageHandler`. - // HYPERLINK ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - // TODO(ianh): deprecate this method: @NotYetDeprecated( - // 'Use tester.binding.defaultBinaryMessenger.setMockDecodedMessageHandler or ' - // 'TestDefaultBinaryMessenger.instance.defaultBinaryMessenger.setMockDecodedMessageHandler instead. ' - // 'This feature was deprecated after v2.1.0-10.0.pre.' - // ) - void setMockMessageHandler(Future Function(T? message)? handler) { - TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockDecodedMessageHandler(this, handler); - } - - /// Shim for `TestDefaultBinaryMessenger.checkMockMessageHandler`. - // HYPERLINK ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - // TODO(ianh): deprecate this method: @NotYetDeprecated( - // 'Use tester.binding.defaultBinaryMessenger.checkMockMessageHandler or ' - // 'TestDefaultBinaryMessenger.instance.defaultBinaryMessenger.checkMockMessageHandler instead. ' - // 'For the first argument, pass channel.name. ' - // 'This feature was deprecated after v2.1.0-10.0.pre.' - // ) - bool checkMockMessageHandler(Object? handler) { - return TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.checkMockMessageHandler(name, handler); - } -} - -/// Shim to support the obsolete [setMockMethodCallHandler] and -/// [checkMockMethodCallHandler] methods on [MethodChannel] in tests. -/// -/// The implementations defer to [TestDefaultBinaryMessengerBinding.defaultBinaryMessenger]. -/// -/// Rather than calling [setMockMethodCallHandler] on the method channel, use -/// `tester.binding.defaultBinaryMessenger.setMockMethodCallHandler` directly. -/// This more accurately represents the actual method invocation. -extension TestMethodChannelExtension on MethodChannel { - /// Shim for `TestDefaultBinaryMessenger.setMockMethodCallHandler`. - // HYPERLINK ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - // TODO(ianh): deprecate this method: @NotYetDeprecated( - // 'Use tester.binding.defaultBinaryMessenger.setMockMethodCallHandler or ' - // 'TestDefaultBinaryMessenger.instance.defaultBinaryMessenger.setMockMethodCallHandler instead. ' - // 'This feature was deprecated after v2.1.0-10.0.pre.' - // ) - void setMockMethodCallHandler(Future? Function(MethodCall call)? handler) { - TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMethodCallHandler(this, handler); - } - - /// Shim for `TestDefaultBinaryMessenger.checkMockMessageHandler`. - // HYPERLINK ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - // TODO(ianh): deprecate this method: @NotYetDeprecated( - // 'Use tester.binding.defaultBinaryMessenger.checkMockMessageHandler or ' - // 'TestDefaultBinaryMessenger.instance.defaultBinaryMessenger.checkMockMessageHandler instead. ' - // 'For the first argument, pass channel.name. ' - // 'This feature was deprecated after v2.1.0-10.0.pre.' - // ) - bool checkMockMethodCallHandler(Object? handler) { - return TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.checkMockMessageHandler(name, handler); - } -} diff --git a/packages/flutter_test/lib/src/event_simulation.dart b/packages/flutter_test/lib/src/event_simulation.dart index f769ab0749..121c20d17c 100644 --- a/packages/flutter_test/lib/src/event_simulation.dart +++ b/packages/flutter_test/lib/src/event_simulation.dart @@ -2,13 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:async'; import 'dart:io'; import 'package:flutter/foundation.dart' show kIsWeb; import 'package:flutter/services.dart'; - -import 'binding.dart'; import 'test_async_utils.dart'; // TODO(gspencergoog): Replace this with more robust key simulation code once @@ -640,20 +637,21 @@ class KeyEventSimulator { assert(_osIsSupported(platform!), 'Platform $platform not supported for key simulation'); final Map data = getKeyData(key, platform: platform!, isDown: true, physicalKey: physicalKey); - final Completer result = Completer(); - await TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.handlePlatformMessage( + bool result = false; + await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage( SystemChannels.keyEvent.name, SystemChannels.keyEvent.codec.encodeMessage(data), (ByteData? data) { if (data == null) { - result.complete(false); return; } final Map decoded = SystemChannels.keyEvent.codec.decodeMessage(data) as Map; - result.complete(decoded['handled'] as bool); + if (decoded['handled'] as bool) { + result = true; + } } ); - return result.future; + return result; }); } @@ -679,7 +677,7 @@ class KeyEventSimulator { final Map data = getKeyData(key, platform: platform!, isDown: false, physicalKey: physicalKey); bool result = false; - await TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.handlePlatformMessage( + await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage( SystemChannels.keyEvent.name, SystemChannels.keyEvent.codec.encodeMessage(data), (ByteData? data) { diff --git a/packages/flutter_test/lib/src/test_default_binary_messenger.dart b/packages/flutter_test/lib/src/test_default_binary_messenger.dart deleted file mode 100644 index d0e18ac5a6..0000000000 --- a/packages/flutter_test/lib/src/test_default_binary_messenger.dart +++ /dev/null @@ -1,306 +0,0 @@ -// Copyright 2014 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'dart:async'; -import 'dart:ui' as ui; - -import 'package:fake_async/fake_async.dart'; -import 'package:flutter/services.dart'; - -/// A [BinaryMessenger] subclass that is used as the default binary messenger -/// under testing environment. -/// -/// It tracks status of data sent across the Flutter platform barrier, which is -/// useful for testing frameworks to monitor and synchronize against the -/// platform messages. -/// -/// ## Messages from the framework to the platform -/// -/// Messages are sent from the framework to the platform via the -/// [send] method. -/// -/// To intercept a message sent from the framework to the platform, -/// consider using [setMockMessageHandler], -/// [setMockDecodedMessageHandler], and [setMockMethodCallHandler] -/// (see also [checkMockMessageHandler]). -/// -/// To wait for all pending framework-to-platform messages, the -/// [platformMessagesFinished] getter provides an appropriate -/// [Future]. The [pendingMessageCount] getter returns the current -/// number of outstanding messages. -/// -/// ## Messages from the platform to the framework -/// -/// The platform sends messages via the [ChannelBuffers] API. Mock -/// messages can be sent to the framework using -/// [handlePlatformMessage]. -/// -/// Listeners for these messages are configured using [setMessageHandler]. -class TestDefaultBinaryMessenger extends BinaryMessenger { - /// Creates a [TestDefaultBinaryMessenger] instance. - /// - /// The [delegate] instance must not be null. - TestDefaultBinaryMessenger(this.delegate): assert(delegate != null); - - /// The delegate [BinaryMessenger]. - final BinaryMessenger delegate; - - // The handlers for messages from the engine (including fake - // messages sent by handlePlatformMessage). - final Map _inboundHandlers = {}; - - /// Send a mock message to the framework as if it came from the platform. - /// - /// If a listener has been set using [setMessageHandler], that listener is - /// invoked to handle the message, and this method returns a future that - /// completes with that handler's result. - /// - /// {@template flutter.flutter_test.TestDefaultBinaryMessenger.handlePlatformMessage.asyncHandlers} - /// It is strongly recommended that all handlers used with this API be - /// synchronous (not requiring any microtasks to complete), because - /// [testWidgets] tests run in a [FakeAsync] zone in which microtasks do not - /// progress except when time is explicitly advanced (e.g. with - /// [WidgetTester.pump]), which means that `await`ing a [Future] will result - /// in the test hanging. - /// {@endtemplate} - /// - /// If no listener is configured, this method returns right away with null. - /// - /// The `callback` argument, if non-null, will be called just before this - /// method's future completes, either with the result of the listener - /// registered with [setMessageHandler], or with null if no listener has - /// been registered. - /// - /// Messages can also be sent via [ChannelBuffers.push] (see - /// [ServicesBinding.channelBuffers]); the effect is the same, though that API - /// will not wait for a response. - // TODO(ianh): When the superclass `handlePlatformMessage` is removed, - // remove this @override (but leave the method). - @override - Future handlePlatformMessage( - String channel, - ByteData? data, - ui.PlatformMessageResponseCallback? callback, - ) { - Future? result; - if (_inboundHandlers.containsKey(channel)) - result = _inboundHandlers[channel]!(data); - result ??= Future.value(null); - if (callback != null) - result = result.then((ByteData? result) { callback(result); return result; }); - return result; - } - - @override - void setMessageHandler(String channel, MessageHandler? handler) { - if (handler == null) { - _inboundHandlers.remove(channel); - delegate.setMessageHandler(channel, null); - } else { - _inboundHandlers[channel] = handler; // used to handle fake messages sent via handlePlatformMessage - delegate.setMessageHandler(channel, handler); // used to handle real messages from the engine - } - } - - final List> _pendingMessages = >[]; - - /// The number of incomplete/pending calls sent to the platform channels. - int get pendingMessageCount => _pendingMessages.length; - - // Handlers that intercept and respond to outgoing messages, - // pretending to be the platform. - final Map _outboundHandlers = {}; - - // The outbound callbacks that were actually registered, so that we - // can implement the [checkMockMessageHandler] method. - final Map _outboundHandlerIdentities = {}; - - @override - Future? send(String channel, ByteData? message) { - final Future? resultFuture; - final MessageHandler? handler = _outboundHandlers[channel]; - if (handler != null) { - resultFuture = handler(message); - } else { - resultFuture = delegate.send(channel, message); - } - if (resultFuture != null) { - _pendingMessages.add(resultFuture); - resultFuture - .catchError((Object error) { /* errors are the responsibility of the caller */ }) - .whenComplete(() => _pendingMessages.remove(resultFuture)); - } - return resultFuture; - } - - /// Returns a Future that completes after all the platform calls are finished. - /// - /// If a new platform message is sent after this method is called, this new - /// message is not tracked. Use with [pendingMessageCount] to guarantee no - /// pending message calls. - Future get platformMessagesFinished { - return Future.wait(_pendingMessages); - } - - /// Set a callback for intercepting messages sent to the platform on - /// the given channel, without decoding them. - /// - /// Intercepted messages are not forwarded to the platform. - /// - /// The given callback will replace the currently registered - /// callback for that channel, if any. To stop intercepting messages - /// at all, pass null as the handler. - /// - /// The handler's return value, if non-null, is used as a response, - /// unencoded. - /// - /// {@macro flutter.flutter_test.TestDefaultBinaryMessenger.handlePlatformMessage.asyncHandlers} - /// - /// The `identity` argument, if non-null, is used to identify the - /// callback when checked by [checkMockMessageHandler]. If null, the - /// `handler` is used instead. (This allows closures to be passed as - /// the `handler` with an alias used as the `identity` so that a - /// reference to the closure need not be used. In practice, this is - /// used by [setMockDecodedMessageHandler] and - /// [setMockMethodCallHandler] to allow [checkMockMessageHandler] to - /// recognize the closures that were passed to those methods even - /// though those methods wrap those closures when passing them to - /// this method.) - /// - /// Registered callbacks are cleared after each test. - /// - /// See also: - /// - /// * [checkMockMessageHandler], which can verify if a handler is still - /// registered, which is useful in tests to ensure that no unexpected - /// handlers are being registered. - /// - /// * [setMockDecodedMessageHandler], which wraps this method but - /// decodes the messages using a [MessageCodec]. - /// - /// * [setMockMethodCallHandler], which wraps this method but decodes - /// the messages using a [MethodCodec]. - void setMockMessageHandler(String channel, MessageHandler? handler, [ Object? identity ]) { - if (handler == null) { - _outboundHandlers.remove(channel); - _outboundHandlerIdentities.remove(channel); - } else { - identity ??= handler; - _outboundHandlers[channel] = handler; - _outboundHandlerIdentities[channel] = identity; - } - } - - /// Set a callback for intercepting messages sent to the platform on - /// the given channel. - /// - /// Intercepted messages are not forwarded to the platform. - /// - /// The given callback will replace the currently registered - /// callback for that channel, if any. To stop intercepting messages - /// at all, pass null as the handler. - /// - /// Messages are decoded using the codec of the channel. - /// - /// The handler's return value, if non-null, is used as a response, - /// after encoding it using the channel's codec. - /// - /// {@macro flutter.flutter_test.TestDefaultBinaryMessenger.handlePlatformMessage.asyncHandlers} - /// - /// Registered callbacks are cleared after each test. - /// - /// See also: - /// - /// * [checkMockMessageHandler], which can verify if a handler is still - /// registered, which is useful in tests to ensure that no unexpected - /// handlers are being registered. - /// - /// * [setMockMessageHandler], which is similar but provides raw - /// access to the underlying bytes. - /// - /// * [setMockMethodCallHandler], which is similar but decodes - /// the messages using a [MethodCodec]. - void setMockDecodedMessageHandler(BasicMessageChannel channel, Future Function(T? message)? handler) { - if (handler == null) { - setMockMessageHandler(channel.name, null); - return; - } - setMockMessageHandler(channel.name, (ByteData? message) async { - return channel.codec.encodeMessage(await handler(channel.codec.decodeMessage(message))); - }, handler); - } - - /// Set a callback for intercepting method calls sent to the - /// platform on the given channel. - /// - /// Intercepted method calls are not forwarded to the platform. - /// - /// The given callback will replace the currently registered - /// callback for that channel, if any. To stop intercepting messages - /// at all, pass null as the handler. - /// - /// Methods are decoded using the codec of the channel. - /// - /// The handler's return value, if non-null, is used as a response, - /// after re-encoding it using the channel's codec. - /// - /// To send an error, throw a [PlatformException] in the handler. - /// Other exceptions are not caught. - /// - /// {@macro flutter.flutter_test.TestDefaultBinaryMessenger.handlePlatformMessage.asyncHandlers} - /// - /// Registered callbacks are cleared after each test. - /// - /// See also: - /// - /// * [checkMockMessageHandler], which can verify if a handler is still - /// registered, which is useful in tests to ensure that no unexpected - /// handlers are being registered. - /// - /// * [setMockMessageHandler], which is similar but provides raw - /// access to the underlying bytes. - /// - /// * [setMockDecodedMessageHandler], which is similar but decodes - /// the messages using a [MessageCodec]. - void setMockMethodCallHandler(MethodChannel channel, Future? Function(MethodCall message)? handler) { - if (handler == null) { - setMockMessageHandler(channel.name, null); - return; - } - setMockMessageHandler(channel.name, (ByteData? message) async { - final MethodCall call = channel.codec.decodeMethodCall(message); - try { - return channel.codec.encodeSuccessEnvelope(await handler(call)); - } on PlatformException catch (error) { - return channel.codec.encodeErrorEnvelope( - code: error.code, - message: error.message, - details: error.details, - ); - } on MissingPluginException { - return null; - } catch (error) { - return channel.codec.encodeErrorEnvelope(code: 'error', message: '$error', details: null); - } - }, handler); - } - - /// Returns true if the `handler` argument matches the `handler` - /// previously passed to [setMockMessageHandler], - /// [setMockDecodedMessageHandler], or [setMockMethodCallHandler]. - /// - /// Specifically, it compares the argument provided to the `identity` - /// argument provided to [setMockMessageHandler], defaulting to the - /// `handler` argument passed to that method is `identity` was null. - /// - /// This method is useful for tests or test harnesses that want to assert the - /// mock handler for the specified channel has not been altered by a previous - /// test. - /// - /// Passing null for the `handler` returns true if the handler for the - /// `channel` is not set. - /// - /// Registered callbacks are cleared after each test. - bool checkMockMessageHandler(String channel, Object? handler) => _outboundHandlerIdentities[channel] == handler; -} diff --git a/packages/flutter_test/lib/src/test_text_input.dart b/packages/flutter_test/lib/src/test_text_input.dart index a99bcef060..63b5979986 100644 --- a/packages/flutter_test/lib/src/test_text_input.dart +++ b/packages/flutter_test/lib/src/test_text_input.dart @@ -8,10 +8,6 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; -import 'binding.dart' show TestDefaultBinaryMessengerBinding; -import 'deprecated.dart'; -import 'test_async_utils.dart'; - export 'package:flutter/services.dart' show TextEditingValue, TextInputAction; /// A testing stub for the system's onscreen keyboard. @@ -49,6 +45,9 @@ class TestTextInput { /// first be requested, e.g. using [WidgetTester.showKeyboard]. final VoidCallback? onCleared; + /// The messenger which sends the bytes for this channel, not null. + BinaryMessenger get _binaryMessenger => ServicesBinding.instance!.defaultBinaryMessenger; + /// Log for method calls. /// /// For all registered channels, handled calls are added to the list. Can @@ -154,25 +153,16 @@ class TestTextInput { _isVisible = false; } - /// Simulates the user changing the text of the focused text field, and resets - /// the selection. + /// 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. /// - /// To update the UI under test after this method is invoked, use - /// [WidgetTester.pump]. - /// /// 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. - /// - /// See also: - /// - /// * [updateEditingValue], which takes a [TextEditingValue] so that one can - /// also change the selection. void enterText(String text) { updateEditingValue(TextEditingValue( text: text, @@ -182,21 +172,13 @@ class TestTextInput { /// Simulates the user changing the [TextEditingValue] to the given value. /// - /// To update the UI under test after this method is invoked, use - /// [WidgetTester.pump]. - /// /// 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. - /// - /// See also: - /// - /// * [enterText], which is similar but takes only a String and resets the - /// selection. void updateEditingValue(TextEditingValue value) { - TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.handlePlatformMessage( + _binaryMessenger.handlePlatformMessage( SystemChannels.textInput.name, SystemChannels.textInput.codec.encodeMethodCall( MethodCall( @@ -204,7 +186,7 @@ class TestTextInput { [_client ?? -1, value.toJSON()], ), ), - (ByteData? data) { /* ignored */ }, + (ByteData? data) { /* response from framework is discarded */ }, ); } @@ -220,7 +202,7 @@ class TestTextInput { Future receiveAction(TextInputAction action) async { return TestAsyncUtils.guard(() { final Completer completer = Completer(); - TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.handlePlatformMessage( + _binaryMessenger.handlePlatformMessage( SystemChannels.textInput.name, SystemChannels.textInput.codec.encodeMethodCall( MethodCall( @@ -234,7 +216,8 @@ class TestTextInput { // Decoding throws a PlatformException if the data represents an // error, and that's all we care about here. SystemChannels.textInput.codec.decodeEnvelope(data!); - // If we reach here then no error was found. Complete without issue. + + // No error was found. Complete without issue. completer.complete(); } catch (error) { // An exception occurred as a result of receiveAction()'ing. Report @@ -243,6 +226,7 @@ class TestTextInput { } }, ); + return completer.future; }); } @@ -260,7 +244,7 @@ class TestTextInput { /// 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() { - TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.handlePlatformMessage( + _binaryMessenger.handlePlatformMessage( SystemChannels.textInput.name, SystemChannels.textInput.codec.encodeMethodCall( MethodCall( diff --git a/packages/flutter_test/lib/src/widget_tester.dart b/packages/flutter_test/lib/src/widget_tester.dart index 50c23a5d91..224bea5fec 100644 --- a/packages/flutter_test/lib/src/widget_tester.dart +++ b/packages/flutter_test/lib/src/widget_tester.dart @@ -129,7 +129,7 @@ void testWidgets( dynamic tags, }) { assert(variant != null); - assert(variant.values.isNotEmpty, 'There must be at least one value to test in the testing variant.'); + assert(variant.values.isNotEmpty, 'There must be at least on value to test in the testing variant'); final TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized() as TestWidgetsFlutterBinding; final WidgetTester tester = WidgetTester._(binding); for (final dynamic value in variant.values) { @@ -147,7 +147,7 @@ void testWidgets( test_package.addTearDown(binding.postTest); return binding.runTest( () async { - binding.reset(); // TODO(ianh): the binding should just do this itself in _runTest + binding.reset(); debugResetSemanticsIdCounter(); Object? memento; try { @@ -917,12 +917,10 @@ class WidgetTester extends WidgetController implements HitTestDispatcher, Ticker /// Acts as if the application went idle. /// /// Runs all remaining microtasks, including those scheduled as a result of - /// running them, until there are no more microtasks scheduled. Then, runs any - /// previously scheduled timers with zero time, and completes the returned future. + /// running them, until there are no more microtasks scheduled. /// - /// May result in an infinite loop or run out of memory if microtasks continue - /// to recursively schedule new microtasks. Will not run any timers scheduled - /// after this method was invoked, even if they are zero-time timers. + /// Does not run timers. May result in an infinite loop or run out of memory + /// if microtasks continue to recursively schedule new microtasks. Future idle() { return TestAsyncUtils.guard(() => binding.idle()); } diff --git a/packages/flutter_test/lib/src/window.dart b/packages/flutter_test/lib/src/window.dart index c27c57d944..500dd68eaf 100644 --- a/packages/flutter_test/lib/src/window.dart +++ b/packages/flutter_test/lib/src/window.dart @@ -379,16 +379,8 @@ class TestWindow implements ui.SingletonFlutterWindow { platformDispatcher.sendPlatformMessage(name, data, callback); } - @Deprecated( - 'Instead of calling this callback, use ServicesBinding.instance.channelBuffers.push. ' - 'This feature was deprecated after v2.1.0-10.0.pre.' - ) @override ui.PlatformMessageCallback? get onPlatformMessage => platformDispatcher.onPlatformMessage; - @Deprecated( - 'Instead of setting this callback, use ServicesBinding.instance.defaultBinaryMessenger.setMessageHandler. ' - 'This feature was deprecated after v2.1.0-10.0.pre.' - ) @override set onPlatformMessage(ui.PlatformMessageCallback? callback) { platformDispatcher.onPlatformMessage = callback; diff --git a/packages/flutter_test/test/test_default_binary_messenger_test.dart b/packages/flutter_test/test/test_default_binary_messenger_test.dart index 30cf93ddf6..82cb18fd64 100644 --- a/packages/flutter_test/test/test_default_binary_messenger_test.dart +++ b/packages/flutter_test/test/test_default_binary_messenger_test.dart @@ -20,6 +20,12 @@ class TestDelegate extends BinaryMessenger { Future handlePlatformMessage(String channel, ByteData? data, ui.PlatformMessageResponseCallback? callback) => throw UnimplementedError(); @override void setMessageHandler(String channel, MessageHandler? handler) => throw UnimplementedError(); + @override + bool checkMessageHandler(String channel, MessageHandler? handler) => throw UnimplementedError(); + @override + void setMockMessageHandler(String channel, MessageHandler? handler) => throw UnimplementedError(); + @override + bool checkMockMessageHandler(String channel, MessageHandler? handler) => throw UnimplementedError(); } void main() { diff --git a/packages/flutter_web_plugins/lib/src/plugin_registry.dart b/packages/flutter_web_plugins/lib/src/plugin_registry.dart index cc397b7c3c..ecd273fc16 100644 --- a/packages/flutter_web_plugins/lib/src/plugin_registry.dart +++ b/packages/flutter_web_plugins/lib/src/plugin_registry.dart @@ -61,7 +61,7 @@ class Registrar extends BinaryMessenger { /// the [dart:ui] library. That function is only available when /// compiling for the web. void registerMessageHandler() { - // The `ui.webOnlySetPluginHandler` function below is only defined in the Web dart:ui. + // The function below is only defined in the Web dart:ui. // ignore: undefined_function ui.webOnlySetPluginHandler(handleFrameworkMessage); } @@ -141,7 +141,7 @@ class Registrar extends BinaryMessenger { @override Future send(String channel, ByteData? message) { final Completer completer = Completer(); - ui.channelBuffers.push(channel, message, (ByteData? reply) { + ui.window.onPlatformMessage!(channel, message, (ByteData? reply) { try { completer.complete(reply); } catch (exception, stack) { @@ -163,6 +163,26 @@ class Registrar extends BinaryMessenger { else _handlers[channel] = handler; } + + @override + bool checkMessageHandler(String channel, MessageHandler? handler) => _handlers[channel] == handler; + + @override + void setMockMessageHandler( + String channel, + MessageHandler? handler, + ) { + throw FlutterError( + 'Setting mock handlers is not supported on the platform side.', + ); + } + + @override + bool checkMockMessageHandler(String channel, MessageHandler? handler) { + throw FlutterError( + 'Setting mock handlers is not supported on the platform side.', + ); + } } /// This class was previously separate from [Registrar] but was merged into it diff --git a/packages/flutter_web_plugins/test/plugin_registry_test.dart b/packages/flutter_web_plugins/test/plugin_registry_test.dart index 73cb681e07..008d721391 100644 --- a/packages/flutter_web_plugins/test/plugin_registry_test.dart +++ b/packages/flutter_web_plugins/test/plugin_registry_test.dart @@ -71,5 +71,12 @@ void main() { ServicesBinding.instance!.defaultBinaryMessenger .setMessageHandler('test_send', null); }); + + test('throws when trying to set a mock handler', () { + expect( + () => pluginBinaryMessenger.setMockMessageHandler( + 'test', (ByteData? data) async => ByteData(0)), + throwsFlutterError); + }); }); }