Migrate to ChannelBuffers.push (#82564)
This commit is contained in:
parent
fa5883b78e
commit
5e0cc4cba4
@ -11,6 +11,6 @@ void main() {
|
|||||||
Ticker((Duration duration) { }).start();
|
Ticker((Duration duration) { }).start();
|
||||||
|
|
||||||
final ByteData? message = const StringCodec().encodeMessage('AppLifecycleState.paused');
|
final ByteData? message = const StringCodec().encodeMessage('AppLifecycleState.paused');
|
||||||
await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage('flutter/lifecycle', message, (_) {});
|
await tester.binding.defaultBinaryMessenger.handlePlatformMessage('flutter/lifecycle', message, (_) {});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -29,9 +29,6 @@ void main() {
|
|||||||
app.main();
|
app.main();
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
// TODO(nurhan): https://github.com/flutter/flutter/issues/51885
|
|
||||||
SystemChannels.textInput.setMockMethodCallHandler(null);
|
|
||||||
|
|
||||||
// Focus on a TextFormField.
|
// Focus on a TextFormField.
|
||||||
final Finder finder = find.byKey(const Key('input'));
|
final Finder finder = find.byKey(const Key('input'));
|
||||||
expect(finder, findsOneWidget);
|
expect(finder, findsOneWidget);
|
||||||
@ -56,9 +53,6 @@ void main() {
|
|||||||
app.main();
|
app.main();
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
// TODO(nurhan): https://github.com/flutter/flutter/issues/51885
|
|
||||||
SystemChannels.textInput.setMockMethodCallHandler(null);
|
|
||||||
|
|
||||||
// Focus on a TextFormField.
|
// Focus on a TextFormField.
|
||||||
final Finder finder = find.byKey(const Key('empty-input'));
|
final Finder finder = find.byKey(const Key('empty-input'));
|
||||||
expect(finder, findsOneWidget);
|
expect(finder, findsOneWidget);
|
||||||
@ -83,9 +77,6 @@ void main() {
|
|||||||
app.main();
|
app.main();
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
// TODO(nurhan): https://github.com/flutter/flutter/issues/51885
|
|
||||||
SystemChannels.textInput.setMockMethodCallHandler(null);
|
|
||||||
|
|
||||||
// This text will show no-enter initially. It will have 'enter-pressed'
|
// This text will show no-enter initially. It will have 'enter-pressed'
|
||||||
// after `onFieldSubmitted` of TextField is triggered.
|
// after `onFieldSubmitted` of TextField is triggered.
|
||||||
final Finder textFinder = find.byKey(const Key('text'));
|
final Finder textFinder = find.byKey(const Key('text'));
|
||||||
@ -118,9 +109,6 @@ void main() {
|
|||||||
app.main();
|
app.main();
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
// TODO(nurhan): https://github.com/flutter/flutter/issues/51885
|
|
||||||
SystemChannels.textInput.setMockMethodCallHandler(null);
|
|
||||||
|
|
||||||
// Focus on a TextFormField.
|
// Focus on a TextFormField.
|
||||||
final Finder finder = find.byKey(const Key('input'));
|
final Finder finder = find.byKey(const Key('input'));
|
||||||
expect(finder, findsOneWidget);
|
expect(finder, findsOneWidget);
|
||||||
@ -152,9 +140,6 @@ void main() {
|
|||||||
app.main();
|
app.main();
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
// TODO(nurhan): https://github.com/flutter/flutter/issues/51885
|
|
||||||
SystemChannels.textInput.setMockMethodCallHandler(null);
|
|
||||||
|
|
||||||
// Focus on a TextFormField.
|
// Focus on a TextFormField.
|
||||||
final Finder finder = find.byKey(const Key('input'));
|
final Finder finder = find.byKey(const Key('input'));
|
||||||
expect(finder, findsOneWidget);
|
expect(finder, findsOneWidget);
|
||||||
@ -203,9 +188,6 @@ void main() {
|
|||||||
app.main();
|
app.main();
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
// TODO(nurhan): https://github.com/flutter/flutter/issues/51885
|
|
||||||
SystemChannels.textInput.setMockMethodCallHandler(null);
|
|
||||||
|
|
||||||
// Select something from the selectable text.
|
// Select something from the selectable text.
|
||||||
final Finder finder = find.byKey(const Key('selectable'));
|
final Finder finder = find.byKey(const Key('selectable'));
|
||||||
expect(finder, findsOneWidget);
|
expect(finder, findsOneWidget);
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:flutter_driver/flutter_driver.dart';
|
import 'package:flutter_driver/flutter_driver.dart';
|
||||||
import 'package:test/test.dart' hide TypeMatcher, isInstanceOf;
|
import 'package:test/test.dart';
|
||||||
import 'package:webdriver/async_io.dart';
|
import 'package:webdriver/async_io.dart';
|
||||||
|
|
||||||
// TODO(web): Migrate this test to a normal integration_test with a WidgetTester.
|
// TODO(web): Migrate this test to a normal integration_test with a WidgetTester.
|
||||||
@ -35,6 +35,7 @@ void main() {
|
|||||||
test('enable accessibility', () async {
|
test('enable accessibility', () async {
|
||||||
await driver.setSemantics(true);
|
await driver.setSemantics(true);
|
||||||
|
|
||||||
|
// TODO(ianh): this delay violates our style guide. We should instead wait for a triggering event.
|
||||||
await Future<void>.delayed(const Duration(seconds: 2));
|
await Future<void>.delayed(const Duration(seconds: 2));
|
||||||
|
|
||||||
// A flutter web app may be rendered directly on the body of the page, or
|
// A flutter web app may be rendered directly on the body of the page, or
|
||||||
|
@ -104,8 +104,8 @@ abstract class BindingBase {
|
|||||||
/// A number of additional bindings are defined as extensions of
|
/// A number of additional bindings are defined as extensions of
|
||||||
/// [BindingBase], e.g., [ServicesBinding], [RendererBinding], and
|
/// [BindingBase], e.g., [ServicesBinding], [RendererBinding], and
|
||||||
/// [WidgetsBinding]. Each of these bindings define behaviors that interact
|
/// [WidgetsBinding]. Each of these bindings define behaviors that interact
|
||||||
/// with a [ui.PlatformDispatcher], e.g., [ServicesBinding] registers a
|
/// with a [ui.PlatformDispatcher], e.g., [ServicesBinding] registers
|
||||||
/// [ui.PlatformDispatcher.onPlatformMessage] handler, and [RendererBinding]
|
/// listeners with the [ChannelBuffers], and [RendererBinding]
|
||||||
/// registers [ui.PlatformDispatcher.onMetricsChanged],
|
/// registers [ui.PlatformDispatcher.onMetricsChanged],
|
||||||
/// [ui.PlatformDispatcher.onTextScaleFactorChanged],
|
/// [ui.PlatformDispatcher.onTextScaleFactorChanged],
|
||||||
/// [ui.PlatformDispatcher.onSemanticsEnabledChanged], and
|
/// [ui.PlatformDispatcher.onSemanticsEnabledChanged], and
|
||||||
|
@ -2,12 +2,9 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
|
||||||
import 'dart:typed_data';
|
import 'dart:typed_data';
|
||||||
import 'dart:ui' as ui;
|
import 'dart:ui' as ui;
|
||||||
|
|
||||||
import 'binding.dart';
|
|
||||||
|
|
||||||
/// A function which takes a platform message and asynchronously returns an encoded response.
|
/// A function which takes a platform message and asynchronously returns an encoded response.
|
||||||
typedef MessageHandler = Future<ByteData?>? Function(ByteData? message);
|
typedef MessageHandler = Future<ByteData?>? Function(ByteData? message);
|
||||||
|
|
||||||
@ -19,12 +16,39 @@ abstract class BinaryMessenger {
|
|||||||
/// const constructors so that they can be used in const expressions.
|
/// const constructors so that they can be used in const expressions.
|
||||||
const BinaryMessenger();
|
const BinaryMessenger();
|
||||||
|
|
||||||
/// Calls the handler registered for the given channel.
|
/// Queues a message.
|
||||||
///
|
///
|
||||||
/// Typically called by [ServicesBinding] to handle platform messages received
|
/// The returned future completes immediately.
|
||||||
/// from [dart:ui.PlatformDispatcher.onPlatformMessage].
|
///
|
||||||
|
/// 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).
|
||||||
///
|
///
|
||||||
/// To register a handler for a given message channel, see [setMessageHandler].
|
/// 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<void> handlePlatformMessage(String channel, ByteData? data, ui.PlatformMessageResponseCallback? callback);
|
Future<void> handlePlatformMessage(String channel, ByteData? data, ui.PlatformMessageResponseCallback? callback);
|
||||||
|
|
||||||
/// Send a binary message to the platform plugins on the given channel.
|
/// Send a binary message to the platform plugins on the given channel.
|
||||||
@ -43,37 +67,6 @@ abstract class BinaryMessenger {
|
|||||||
/// The handler's return value, if non-null, is sent as a response, unencoded.
|
/// The handler's return value, if non-null, is sent as a response, unencoded.
|
||||||
void setMessageHandler(String channel, MessageHandler? handler);
|
void setMessageHandler(String channel, MessageHandler? handler);
|
||||||
|
|
||||||
/// Returns true if the `handler` argument matches the `handler` previously
|
// Looking for setMockMessageHandler or checkMockMessageHandler?
|
||||||
/// passed to [setMessageHandler].
|
// See this shim package: packages/flutter_test/lib/src/deprecated.dart
|
||||||
///
|
|
||||||
/// 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);
|
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,6 @@ mixin ServicesBinding on BindingBase, SchedulerBinding {
|
|||||||
_instance = this;
|
_instance = this;
|
||||||
_defaultBinaryMessenger = createBinaryMessenger();
|
_defaultBinaryMessenger = createBinaryMessenger();
|
||||||
_restorationManager = createRestorationManager();
|
_restorationManager = createRestorationManager();
|
||||||
window.onPlatformMessage = defaultBinaryMessenger.handlePlatformMessage;
|
|
||||||
initLicenses();
|
initLicenses();
|
||||||
SystemChannels.system.setMessageHandler((dynamic message) => handleSystemMessage(message as Object));
|
SystemChannels.system.setMessageHandler((dynamic message) => handleSystemMessage(message as Object));
|
||||||
SystemChannels.lifecycle.setMessageHandler(_handleLifecycleMessage);
|
SystemChannels.lifecycle.setMessageHandler(_handleLifecycleMessage);
|
||||||
@ -49,6 +48,28 @@ mixin ServicesBinding on BindingBase, SchedulerBinding {
|
|||||||
BinaryMessenger get defaultBinaryMessenger => _defaultBinaryMessenger;
|
BinaryMessenger get defaultBinaryMessenger => _defaultBinaryMessenger;
|
||||||
late BinaryMessenger _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
|
/// Creates a default [BinaryMessenger] instance that can be used for sending
|
||||||
/// platform messages.
|
/// platform messages.
|
||||||
@protected
|
@protected
|
||||||
@ -56,7 +77,6 @@ mixin ServicesBinding on BindingBase, SchedulerBinding {
|
|||||||
return const _DefaultBinaryMessenger._();
|
return const _DefaultBinaryMessenger._();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Called when the operating system notifies the application of a memory
|
/// Called when the operating system notifies the application of a memory
|
||||||
/// pressure situation.
|
/// pressure situation.
|
||||||
///
|
///
|
||||||
@ -253,17 +273,20 @@ mixin ServicesBinding on BindingBase, SchedulerBinding {
|
|||||||
class _DefaultBinaryMessenger extends BinaryMessenger {
|
class _DefaultBinaryMessenger extends BinaryMessenger {
|
||||||
const _DefaultBinaryMessenger._();
|
const _DefaultBinaryMessenger._();
|
||||||
|
|
||||||
// Handlers for incoming messages from platform plugins.
|
@override
|
||||||
// This is static so that this class can have a const constructor.
|
Future<void> handlePlatformMessage(
|
||||||
static final Map<String, MessageHandler> _handlers =
|
String channel,
|
||||||
<String, MessageHandler>{};
|
ByteData? message,
|
||||||
|
ui.PlatformMessageResponseCallback? callback,
|
||||||
|
) async {
|
||||||
|
ui.channelBuffers.push(channel, message, (ByteData? data) {
|
||||||
|
if (callback != null)
|
||||||
|
callback(data);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Mock handlers that intercept and respond to outgoing messages.
|
@override
|
||||||
// This is static so that this class can have a const constructor.
|
Future<ByteData?> send(String channel, ByteData? message) {
|
||||||
static final Map<String, MessageHandler> _mockHandlers =
|
|
||||||
<String, MessageHandler>{};
|
|
||||||
|
|
||||||
Future<ByteData?> _sendPlatformMessage(String channel, ByteData? message) {
|
|
||||||
final Completer<ByteData?> completer = Completer<ByteData?>();
|
final Completer<ByteData?> completer = Completer<ByteData?>();
|
||||||
// ui.PlatformDispatcher.instance is accessed directly instead of using
|
// ui.PlatformDispatcher.instance is accessed directly instead of using
|
||||||
// ServicesBinding.instance.platformDispatcher because this method might be
|
// ServicesBinding.instance.platformDispatcher because this method might be
|
||||||
@ -272,6 +295,8 @@ class _DefaultBinaryMessenger extends BinaryMessenger {
|
|||||||
// ui.PlatformDispatcher.instance because the PlatformDispatcher may be
|
// ui.PlatformDispatcher.instance because the PlatformDispatcher may be
|
||||||
// dependency injected elsewhere with a different instance. However, static
|
// dependency injected elsewhere with a different instance. However, static
|
||||||
// access at this location seems to be the least bad option.
|
// 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) {
|
ui.PlatformDispatcher.instance.sendPlatformMessage(channel, message, (ByteData? reply) {
|
||||||
try {
|
try {
|
||||||
completer.complete(reply);
|
completer.complete(reply);
|
||||||
@ -287,67 +312,27 @@ class _DefaultBinaryMessenger extends BinaryMessenger {
|
|||||||
return completer.future;
|
return completer.future;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
@pragma('vm:notify-debugger-on-exception')
|
|
||||||
Future<void> 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<ByteData?>? send(String channel, ByteData? message) {
|
|
||||||
final MessageHandler? handler = _mockHandlers[channel];
|
|
||||||
if (handler != null)
|
|
||||||
return handler(message);
|
|
||||||
return _sendPlatformMessage(channel, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void setMessageHandler(String channel, MessageHandler? handler) {
|
void setMessageHandler(String channel, MessageHandler? handler) {
|
||||||
if (handler == null) {
|
if (handler == null) {
|
||||||
_handlers.remove(channel);
|
ui.channelBuffers.clearListener(channel);
|
||||||
} else {
|
} else {
|
||||||
_handlers[channel] = handler;
|
ui.channelBuffers.setListener(channel, (ByteData? data, ui.PlatformMessageResponseCallback callback) async {
|
||||||
ui.channelBuffers.drain(channel, (ByteData? data, ui.PlatformMessageResponseCallback callback) async {
|
ByteData? response;
|
||||||
await handlePlatformMessage(channel, data, callback);
|
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);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@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;
|
|
||||||
}
|
}
|
||||||
|
@ -95,7 +95,6 @@ abstract class MethodCodec {
|
|||||||
ByteData encodeErrorEnvelope({ required String code, String? message, Object? details});
|
ByteData encodeErrorEnvelope({ required String code, String? message, Object? details});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Thrown to indicate that a platform interaction failed in the platform
|
/// Thrown to indicate that a platform interaction failed in the platform
|
||||||
/// plugin.
|
/// plugin.
|
||||||
///
|
///
|
||||||
|
@ -75,31 +75,10 @@ class BasicMessageChannel<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets a mock callback for intercepting messages sent on this channel.
|
// Looking for setMockMessageHandler?
|
||||||
/// Messages may be null.
|
// See this shim package: packages/flutter_test/lib/src/deprecated.dart
|
||||||
///
|
|
||||||
/// 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<T> 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<Object> _methodChannelHandlers = Expando<Object>();
|
|
||||||
Expando<Object> _methodChannelMockHandlers = Expando<Object>();
|
|
||||||
|
|
||||||
/// A named channel for communicating with platform plugins using asynchronous
|
/// A named channel for communicating with platform plugins using asynchronous
|
||||||
/// method calls.
|
/// method calls.
|
||||||
///
|
///
|
||||||
@ -393,7 +372,6 @@ class MethodChannel {
|
|||||||
/// similarly to what happens if no method call handler has been set.
|
/// similarly to what happens if no method call handler has been set.
|
||||||
/// Any other exception results in an error envelope being sent.
|
/// Any other exception results in an error envelope being sent.
|
||||||
void setMethodCallHandler(Future<dynamic> Function(MethodCall call)? handler) {
|
void setMethodCallHandler(Future<dynamic> Function(MethodCall call)? handler) {
|
||||||
_methodChannelHandlers[this] = handler;
|
|
||||||
binaryMessenger.setMessageHandler(
|
binaryMessenger.setMessageHandler(
|
||||||
name,
|
name,
|
||||||
handler == null
|
handler == null
|
||||||
@ -402,53 +380,7 @@ class MethodChannel {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if the `handler` argument matches the `handler` previously
|
Future<ByteData?> _handleAsMethodCall(ByteData? message, Future<dynamic> Function(MethodCall call) handler) async {
|
||||||
/// 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<dynamic> 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<dynamic>? 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<dynamic> Function(MethodCall call)? handler) => _methodChannelMockHandlers[this] == handler;
|
|
||||||
|
|
||||||
Future<ByteData?> _handleAsMethodCall(ByteData? message, Future<dynamic>? Function(MethodCall call) handler) async {
|
|
||||||
final MethodCall call = codec.decodeMethodCall(message);
|
final MethodCall call = codec.decodeMethodCall(message);
|
||||||
try {
|
try {
|
||||||
return codec.encodeSuccessEnvelope(await handler(call));
|
return codec.encodeSuccessEnvelope(await handler(call));
|
||||||
@ -464,6 +396,9 @@ class MethodChannel {
|
|||||||
return codec.encodeErrorEnvelope(code: 'error', message: e.toString(), details: null);
|
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.
|
/// A [MethodChannel] that ignores missing platform plugins.
|
||||||
|
@ -166,7 +166,6 @@ class RestorationManager extends ChangeNotifier {
|
|||||||
/// that communications channel, or to set it up differently, as necessary.
|
/// that communications channel, or to set it up differently, as necessary.
|
||||||
@protected
|
@protected
|
||||||
void initChannels() {
|
void initChannels() {
|
||||||
assert(!SystemChannels.restoration.checkMethodCallHandler(_methodHandler));
|
|
||||||
SystemChannels.restoration.setMethodCallHandler(_methodHandler);
|
SystemChannels.restoration.setMethodCallHandler(_methodHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,6 +129,11 @@ class SystemChannels {
|
|||||||
/// they apply, so that stale messages referencing past transactions can be
|
/// they apply, so that stale messages referencing past transactions can be
|
||||||
/// ignored.
|
/// ignored.
|
||||||
///
|
///
|
||||||
|
/// In debug builds, messages sent with a client ID of -1 are always accepted.
|
||||||
|
/// This allows tests to smuggle messages without having to mock the engine's
|
||||||
|
/// text handling (for example, allowing the engine to still handle the text
|
||||||
|
/// input messages in an integration test).
|
||||||
|
///
|
||||||
/// The methods described below are wrapped in a more convenient form by the
|
/// The methods described below are wrapped in a more convenient form by the
|
||||||
/// [TextInput] and [TextInputConnection] class.
|
/// [TextInput] and [TextInputConnection] class.
|
||||||
///
|
///
|
||||||
@ -161,9 +166,15 @@ class SystemChannels {
|
|||||||
/// is a transaction identifier. Calls for stale transactions should be ignored.
|
/// is a transaction identifier. Calls for stale transactions should be ignored.
|
||||||
///
|
///
|
||||||
/// * `TextInputClient.updateEditingState`: The user has changed the contents
|
/// * `TextInputClient.updateEditingState`: The user has changed the contents
|
||||||
/// of the text control. The second argument is a [String] containing a
|
/// of the text control. The second argument is an object with seven keys,
|
||||||
/// JSON-encoded object with seven keys, in the form expected by
|
/// in the form expected by [TextEditingValue.fromJSON].
|
||||||
/// [TextEditingValue.fromJSON].
|
///
|
||||||
|
/// * `TextInputClient.updateEditingStateWithTag`: One or more text controls
|
||||||
|
/// were autofilled by the platform's autofill service. The first argument
|
||||||
|
/// (the client ID) is ignored, the second argument is a map of tags to
|
||||||
|
/// objects in the form expected by [TextEditingValue.fromJSON]. See
|
||||||
|
/// [AutofillScope.getAutofillClient] for details on the interpretation of
|
||||||
|
/// the tag.
|
||||||
///
|
///
|
||||||
/// * `TextInputClient.performAction`: The user has triggered an action. The
|
/// * `TextInputClient.performAction`: The user has triggered an action. The
|
||||||
/// second argument is a [String] consisting of the stringification of one
|
/// second argument is a [String] consisting of the stringification of one
|
||||||
@ -174,7 +185,8 @@ class SystemChannels {
|
|||||||
/// one. The framework should call `TextInput.setClient` and
|
/// one. The framework should call `TextInput.setClient` and
|
||||||
/// `TextInput.setEditingState` again with its most recent information. If
|
/// `TextInput.setEditingState` again with its most recent information. If
|
||||||
/// there is no existing state on the framework side, the call should
|
/// there is no existing state on the framework side, the call should
|
||||||
/// fizzle.
|
/// fizzle. (This call is made without a client ID; indeed, without any
|
||||||
|
/// arguments at all.)
|
||||||
///
|
///
|
||||||
/// * `TextInputClient.onConnectionClosed`: The text input connection closed
|
/// * `TextInputClient.onConnectionClosed`: The text input connection closed
|
||||||
/// on the platform side. For example the application is moved to
|
/// on the platform side. For example the application is moved to
|
||||||
|
@ -1327,9 +1327,11 @@ class TextInput {
|
|||||||
|
|
||||||
final List<dynamic> args = methodCall.arguments as List<dynamic>;
|
final List<dynamic> args = methodCall.arguments as List<dynamic>;
|
||||||
|
|
||||||
|
// The updateEditingStateWithTag request (autofill) can come up even to a
|
||||||
|
// text field that doesn't have a connection.
|
||||||
if (method == 'TextInputClient.updateEditingStateWithTag') {
|
if (method == 'TextInputClient.updateEditingStateWithTag') {
|
||||||
|
assert(_currentConnection!._client != null);
|
||||||
final TextInputClient client = _currentConnection!._client;
|
final TextInputClient client = _currentConnection!._client;
|
||||||
assert(client != null);
|
|
||||||
final AutofillScope? scope = client.currentAutofillScope;
|
final AutofillScope? scope = client.currentAutofillScope;
|
||||||
final Map<String, dynamic> editingValue = args[1] as Map<String, dynamic>;
|
final Map<String, dynamic> editingValue = args[1] as Map<String, dynamic>;
|
||||||
for (final String tag in editingValue.keys) {
|
for (final String tag in editingValue.keys) {
|
||||||
@ -1343,9 +1345,22 @@ class TextInput {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final int client = args[0] as int;
|
final int client = args[0] as int;
|
||||||
// The incoming message was for a different client.
|
if (client != _currentConnection!._id) {
|
||||||
if (client != _currentConnection!._id)
|
// If the client IDs don't match, the incoming message was for a different
|
||||||
return;
|
// client.
|
||||||
|
bool debugAllowAnyway = false;
|
||||||
|
assert(() {
|
||||||
|
// In debug builds we allow "-1" as a magical client ID that ignores
|
||||||
|
// this verification step so that tests can always get through, even
|
||||||
|
// when they are not mocking the engine side of text input.
|
||||||
|
if (client == -1)
|
||||||
|
debugAllowAnyway = true;
|
||||||
|
return true;
|
||||||
|
}());
|
||||||
|
if (!debugAllowAnyway)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
switch (method) {
|
switch (method) {
|
||||||
case 'TextInputClient.updateEditingState':
|
case 'TextInputClient.updateEditingState':
|
||||||
_currentConnection!._client.updateEditingValue(TextEditingValue.fromJSON(args[1] as Map<String, dynamic>));
|
_currentConnection!._client.updateEditingValue(TextEditingValue.fromJSON(args[1] as Map<String, dynamic>));
|
||||||
@ -1502,7 +1517,7 @@ class TextInput {
|
|||||||
assert(shouldSave != null);
|
assert(shouldSave != null);
|
||||||
TextInput._instance._channel.invokeMethod<void>(
|
TextInput._instance._channel.invokeMethod<void>(
|
||||||
'TextInput.finishAutofillContext',
|
'TextInput.finishAutofillContext',
|
||||||
shouldSave ,
|
shouldSave,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2112,7 +2112,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
|
|||||||
if (_hasFocus) {
|
if (_hasFocus) {
|
||||||
_openInputConnection();
|
_openInputConnection();
|
||||||
} else {
|
} else {
|
||||||
widget.focusNode.requestFocus();
|
widget.focusNode.requestFocus(); // This eventually calls _openInputConnection also, see _handleFocusChanged.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2360,11 +2360,13 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
|
|||||||
|
|
||||||
void _cursorWaitForStart(Timer timer) {
|
void _cursorWaitForStart(Timer timer) {
|
||||||
assert(_kCursorBlinkHalfPeriod > _fadeDuration);
|
assert(_kCursorBlinkHalfPeriod > _fadeDuration);
|
||||||
|
assert(!EditableText.debugDeterministicCursor);
|
||||||
_cursorTimer?.cancel();
|
_cursorTimer?.cancel();
|
||||||
_cursorTimer = Timer.periodic(_kCursorBlinkHalfPeriod, _cursorTick);
|
_cursorTimer = Timer.periodic(_kCursorBlinkHalfPeriod, _cursorTick);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _startCursorTimer() {
|
void _startCursorTimer() {
|
||||||
|
assert(_cursorTimer == null);
|
||||||
_targetCursorVisibility = true;
|
_targetCursorVisibility = true;
|
||||||
_cursorBlinkOpacityController.value = 1.0;
|
_cursorBlinkOpacityController.value = 1.0;
|
||||||
if (EditableText.debugDeterministicCursor)
|
if (EditableText.debugDeterministicCursor)
|
||||||
|
@ -201,7 +201,7 @@ void main() {
|
|||||||
final List<int> selectedItems = <int>[];
|
final List<int> selectedItems = <int>[];
|
||||||
final List<MethodCall> systemCalls = <MethodCall>[];
|
final List<MethodCall> systemCalls = <MethodCall>[];
|
||||||
|
|
||||||
SystemChannels.platform.setMockMethodCallHandler((MethodCall methodCall) async {
|
tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async {
|
||||||
systemCalls.add(methodCall);
|
systemCalls.add(methodCall);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -254,7 +254,7 @@ void main() {
|
|||||||
final List<int> selectedItems = <int>[];
|
final List<int> selectedItems = <int>[];
|
||||||
final List<MethodCall> systemCalls = <MethodCall>[];
|
final List<MethodCall> systemCalls = <MethodCall>[];
|
||||||
|
|
||||||
SystemChannels.platform.setMockMethodCallHandler((MethodCall methodCall) async {
|
tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async {
|
||||||
systemCalls.add(methodCall);
|
systemCalls.add(methodCall);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -175,7 +175,7 @@ void main() {
|
|||||||
testWidgets('drag past threshold triggers refresh task', (WidgetTester tester) async {
|
testWidgets('drag past threshold triggers refresh task', (WidgetTester tester) async {
|
||||||
final List<MethodCall> platformCallLog = <MethodCall>[];
|
final List<MethodCall> platformCallLog = <MethodCall>[];
|
||||||
|
|
||||||
SystemChannels.platform.setMockMethodCallHandler((MethodCall methodCall) async {
|
tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async {
|
||||||
platformCallLog.add(methodCall);
|
platformCallLog.add(methodCall);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -132,9 +132,9 @@ void main() {
|
|||||||
await tester.pump();
|
await tester.pump();
|
||||||
|
|
||||||
int hapticFeedbackCalls = 0;
|
int hapticFeedbackCalls = 0;
|
||||||
SystemChannels.platform.setMockMethodCallHandler((MethodCall methodCall) async {
|
tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async {
|
||||||
if (methodCall.method == 'HapticFeedback.vibrate') {
|
if (methodCall.method == 'HapticFeedback.vibrate') {
|
||||||
hapticFeedbackCalls++;
|
hapticFeedbackCalls += 1;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -692,9 +692,9 @@ void main() {
|
|||||||
await tester.pump();
|
await tester.pump();
|
||||||
|
|
||||||
int hapticFeedbackCalls = 0;
|
int hapticFeedbackCalls = 0;
|
||||||
SystemChannels.platform.setMockMethodCallHandler((MethodCall methodCall) async {
|
tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async {
|
||||||
if (methodCall.method == 'HapticFeedback.vibrate') {
|
if (methodCall.method == 'HapticFeedback.vibrate') {
|
||||||
hapticFeedbackCalls++;
|
hapticFeedbackCalls += 1;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ void main() {
|
|||||||
|
|
||||||
final List<MethodCall> log = <MethodCall>[];
|
final List<MethodCall> log = <MethodCall>[];
|
||||||
|
|
||||||
SystemChannels.platform.setMockMethodCallHandler((MethodCall methodCall) async {
|
tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async {
|
||||||
log.add(methodCall);
|
log.add(methodCall);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -87,7 +87,7 @@ void main() {
|
|||||||
bool value2 = false;
|
bool value2 = false;
|
||||||
final List<MethodCall> log = <MethodCall>[];
|
final List<MethodCall> log = <MethodCall>[];
|
||||||
|
|
||||||
SystemChannels.platform.setMockMethodCallHandler((MethodCall methodCall) async {
|
tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async {
|
||||||
log.add(methodCall);
|
log.add(methodCall);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -154,7 +154,7 @@ void main() {
|
|||||||
bool value = false;
|
bool value = false;
|
||||||
final List<MethodCall> log = <MethodCall>[];
|
final List<MethodCall> log = <MethodCall>[];
|
||||||
|
|
||||||
SystemChannels.platform.setMockMethodCallHandler((MethodCall methodCall) async {
|
tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async {
|
||||||
log.add(methodCall);
|
log.add(methodCall);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -192,7 +192,7 @@ void main() {
|
|||||||
bool value = false;
|
bool value = false;
|
||||||
|
|
||||||
final List<MethodCall> log = <MethodCall>[];
|
final List<MethodCall> log = <MethodCall>[];
|
||||||
SystemChannels.platform.setMockMethodCallHandler((MethodCall methodCall) async {
|
tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async {
|
||||||
log.add(methodCall);
|
log.add(methodCall);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -162,7 +162,7 @@ class PathPointsMatcher extends Matcher {
|
|||||||
void main() {
|
void main() {
|
||||||
TestWidgetsFlutterBinding.ensureInitialized();
|
TestWidgetsFlutterBinding.ensureInitialized();
|
||||||
final MockClipboard mockClipboard = MockClipboard();
|
final MockClipboard mockClipboard = MockClipboard();
|
||||||
SystemChannels.platform.setMockMethodCallHandler(mockClipboard.handleMethodCall);
|
TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, mockClipboard.handleMethodCall);
|
||||||
|
|
||||||
// Returns the first RenderEditable.
|
// Returns the first RenderEditable.
|
||||||
RenderEditable findRenderEditable(WidgetTester tester) {
|
RenderEditable findRenderEditable(WidgetTester tester) {
|
||||||
@ -3228,7 +3228,7 @@ void main() {
|
|||||||
|
|
||||||
testWidgets('text field respects keyboardAppearance from theme', (WidgetTester tester) async {
|
testWidgets('text field respects keyboardAppearance from theme', (WidgetTester tester) async {
|
||||||
final List<MethodCall> log = <MethodCall>[];
|
final List<MethodCall> log = <MethodCall>[];
|
||||||
SystemChannels.textInput.setMockMethodCallHandler((MethodCall methodCall) async {
|
tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.textInput, (MethodCall methodCall) async {
|
||||||
log.add(methodCall);
|
log.add(methodCall);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -3251,7 +3251,7 @@ void main() {
|
|||||||
|
|
||||||
testWidgets('text field can override keyboardAppearance from theme', (WidgetTester tester) async {
|
testWidgets('text field can override keyboardAppearance from theme', (WidgetTester tester) async {
|
||||||
final List<MethodCall> log = <MethodCall>[];
|
final List<MethodCall> log = <MethodCall>[];
|
||||||
SystemChannels.textInput.setMockMethodCallHandler((MethodCall methodCall) async {
|
tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.textInput, (MethodCall methodCall) async {
|
||||||
log.add(methodCall);
|
log.add(methodCall);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@ const _LongCupertinoLocalizations _longLocalizations = _LongCupertinoLocalizatio
|
|||||||
void main() {
|
void main() {
|
||||||
TestWidgetsFlutterBinding.ensureInitialized();
|
TestWidgetsFlutterBinding.ensureInitialized();
|
||||||
final MockClipboard mockClipboard = MockClipboard();
|
final MockClipboard mockClipboard = MockClipboard();
|
||||||
SystemChannels.platform.setMockMethodCallHandler(mockClipboard.handleMethodCall);
|
TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, mockClipboard.handleMethodCall);
|
||||||
|
|
||||||
// Returns true iff the button is visually enabled.
|
// Returns true iff the button is visually enabled.
|
||||||
bool appearsEnabled(WidgetTester tester, String text) {
|
bool appearsEnabled(WidgetTester tester, String text) {
|
||||||
|
@ -21,7 +21,8 @@ class TestServiceExtensionsBinding extends BindingBase
|
|||||||
PaintingBinding,
|
PaintingBinding,
|
||||||
SemanticsBinding,
|
SemanticsBinding,
|
||||||
RendererBinding,
|
RendererBinding,
|
||||||
WidgetsBinding {
|
WidgetsBinding,
|
||||||
|
TestDefaultBinaryMessengerBinding {
|
||||||
|
|
||||||
final Map<String, ServiceExtensionCallback> extensions = <String, ServiceExtensionCallback>{};
|
final Map<String, ServiceExtensionCallback> extensions = <String, ServiceExtensionCallback>{};
|
||||||
|
|
||||||
@ -467,7 +468,7 @@ void main() {
|
|||||||
bool completed;
|
bool completed;
|
||||||
|
|
||||||
completed = false;
|
completed = false;
|
||||||
ServicesBinding.instance!.defaultBinaryMessenger.setMockMessageHandler('flutter/assets', (ByteData? message) async {
|
TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMessageHandler('flutter/assets', (ByteData? message) async {
|
||||||
expect(utf8.decode(message!.buffer.asUint8List()), 'test');
|
expect(utf8.decode(message!.buffer.asUint8List()), 'test');
|
||||||
completed = true;
|
completed = true;
|
||||||
return ByteData(5); // 0x0000000000
|
return ByteData(5); // 0x0000000000
|
||||||
@ -494,7 +495,7 @@ void main() {
|
|||||||
});
|
});
|
||||||
expect(data, isFalse);
|
expect(data, isFalse);
|
||||||
expect(completed, isTrue);
|
expect(completed, isTrue);
|
||||||
ServicesBinding.instance!.defaultBinaryMessenger.setMockMessageHandler('flutter/assets', null);
|
TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMessageHandler('flutter/assets', null);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Service extensions - exit', () async {
|
test('Service extensions - exit', () async {
|
||||||
|
@ -2,12 +2,6 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// 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 'dart:ui' as ui;
|
||||||
|
|
||||||
import 'package:clock/clock.dart';
|
import 'package:clock/clock.dart';
|
||||||
|
@ -267,7 +267,7 @@ void main() {
|
|||||||
testWidgets('has semantic events', (WidgetTester tester) async {
|
testWidgets('has semantic events', (WidgetTester tester) async {
|
||||||
dynamic semanticEvent;
|
dynamic semanticEvent;
|
||||||
bool? checkboxValue = false;
|
bool? checkboxValue = false;
|
||||||
SystemChannels.accessibility.setMockMessageHandler((dynamic message) async {
|
tester.binding.defaultBinaryMessenger.setMockDecodedMessageHandler<dynamic>(SystemChannels.accessibility, (dynamic message) async {
|
||||||
semanticEvent = message;
|
semanticEvent = message;
|
||||||
});
|
});
|
||||||
final SemanticsTester semanticsTester = SemanticsTester(tester);
|
final SemanticsTester semanticsTester = SemanticsTester(tester);
|
||||||
@ -300,7 +300,7 @@ void main() {
|
|||||||
});
|
});
|
||||||
expect(object.debugSemantics!.getSemanticsData().hasAction(SemanticsAction.tap), true);
|
expect(object.debugSemantics!.getSemanticsData().hasAction(SemanticsAction.tap), true);
|
||||||
|
|
||||||
SystemChannels.accessibility.setMockMessageHandler(null);
|
tester.binding.defaultBinaryMessenger.setMockDecodedMessageHandler<dynamic>(SystemChannels.accessibility, null);
|
||||||
semanticsTester.dispose();
|
semanticsTester.dispose();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -27,14 +27,14 @@ void main () {
|
|||||||
|
|
||||||
setUp(() {
|
setUp(() {
|
||||||
semanticEvents = <Map<String, Object>>[];
|
semanticEvents = <Map<String, Object>>[];
|
||||||
SystemChannels.accessibility.setMockMessageHandler((dynamic message) async {
|
TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockDecodedMessageHandler<dynamic>(SystemChannels.accessibility, (dynamic message) async {
|
||||||
final Map<dynamic, dynamic> typedMessage = message as Map<dynamic, dynamic>;
|
final Map<dynamic, dynamic> typedMessage = message as Map<dynamic, dynamic>;
|
||||||
semanticEvents.add(typedMessage.cast<String, Object>());
|
semanticEvents.add(typedMessage.cast<String, Object>());
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
tearDown(() {
|
tearDown(() {
|
||||||
SystemChannels.accessibility.setMockMessageHandler(null);
|
TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockDecodedMessageHandler<dynamic>(SystemChannels.accessibility, null);
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('forTap', (WidgetTester tester) async {
|
testWidgets('forTap', (WidgetTester tester) async {
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
|
||||||
/// Tracks how often feedback has been requested since its instantiation.
|
/// Tracks how often feedback has been requested since its instantiation.
|
||||||
///
|
///
|
||||||
@ -10,13 +11,7 @@ import 'package:flutter/services.dart';
|
|||||||
/// cannot be used in combination with other classes that do the same.
|
/// cannot be used in combination with other classes that do the same.
|
||||||
class FeedbackTester {
|
class FeedbackTester {
|
||||||
FeedbackTester() {
|
FeedbackTester() {
|
||||||
SystemChannels.platform.setMockMethodCallHandler((MethodCall methodCall) async {
|
TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, _handler);
|
||||||
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).
|
/// Number of times haptic feedback was requested (vibration).
|
||||||
@ -27,8 +22,17 @@ class FeedbackTester {
|
|||||||
int get clickSoundCount => _clickSoundCount;
|
int get clickSoundCount => _clickSoundCount;
|
||||||
int _clickSoundCount = 0;
|
int _clickSoundCount = 0;
|
||||||
|
|
||||||
|
Future<void> _handler(MethodCall methodCall) async {
|
||||||
|
if (methodCall.method == 'HapticFeedback.vibrate')
|
||||||
|
_hapticCount++;
|
||||||
|
if (methodCall.method == 'SystemSound.play' &&
|
||||||
|
methodCall.arguments == SystemSoundType.click.toString())
|
||||||
|
_clickSoundCount++;
|
||||||
|
}
|
||||||
|
|
||||||
/// Stops tracking.
|
/// Stops tracking.
|
||||||
void dispose() {
|
void dispose() {
|
||||||
SystemChannels.platform.setMockMethodCallHandler(null);
|
assert(TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.checkMockMessageHandler(SystemChannels.platform.name, _handler));
|
||||||
|
TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -241,9 +241,9 @@ void main() {
|
|||||||
|
|
||||||
// Fill the clipboard so that the Paste option is available in the text
|
// Fill the clipboard so that the Paste option is available in the text
|
||||||
// selection menu.
|
// selection menu.
|
||||||
SystemChannels.platform.setMockMethodCallHandler(mockClipboard.handleMethodCall);
|
tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, mockClipboard.handleMethodCall);
|
||||||
await Clipboard.setData(const ClipboardData(text: 'Clipboard data'));
|
await Clipboard.setData(const ClipboardData(text: 'Clipboard data'));
|
||||||
addTearDown(() => SystemChannels.platform.setMockMethodCallHandler(null));
|
addTearDown(() => tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, null));
|
||||||
|
|
||||||
await tester.pumpWidget(_inputDatePickerField(autofocus: true));
|
await tester.pumpWidget(_inputDatePickerField(autofocus: true));
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
|
@ -537,7 +537,7 @@ void main() {
|
|||||||
final Key key = UniqueKey();
|
final Key key = UniqueKey();
|
||||||
dynamic semanticEvent;
|
dynamic semanticEvent;
|
||||||
int? radioValue = 2;
|
int? radioValue = 2;
|
||||||
SystemChannels.accessibility.setMockMessageHandler((dynamic message) async {
|
tester.binding.defaultBinaryMessenger.setMockDecodedMessageHandler<dynamic>(SystemChannels.accessibility, (dynamic message) async {
|
||||||
semanticEvent = message;
|
semanticEvent = message;
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -568,7 +568,7 @@ void main() {
|
|||||||
expect(object.debugSemantics!.getSemanticsData().hasAction(SemanticsAction.tap), true);
|
expect(object.debugSemantics!.getSemanticsData().hasAction(SemanticsAction.tap), true);
|
||||||
|
|
||||||
semantics.dispose();
|
semantics.dispose();
|
||||||
SystemChannels.accessibility.setMockMessageHandler(null);
|
tester.binding.defaultBinaryMessenger.setMockDecodedMessageHandler<dynamic>(SystemChannels.accessibility, null);
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('RadioListTile can autofocus unless disabled.', (WidgetTester tester) async {
|
testWidgets('RadioListTile can autofocus unless disabled.', (WidgetTester tester) async {
|
||||||
|
@ -292,7 +292,7 @@ void main() {
|
|||||||
final Key key = UniqueKey();
|
final Key key = UniqueKey();
|
||||||
dynamic semanticEvent;
|
dynamic semanticEvent;
|
||||||
int? radioValue = 2;
|
int? radioValue = 2;
|
||||||
SystemChannels.accessibility.setMockMessageHandler((dynamic message) async {
|
tester.binding.defaultBinaryMessenger.setMockDecodedMessageHandler<dynamic>(SystemChannels.accessibility, (dynamic message) async {
|
||||||
semanticEvent = message;
|
semanticEvent = message;
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -319,7 +319,7 @@ void main() {
|
|||||||
expect(object.debugSemantics!.getSemanticsData().hasAction(SemanticsAction.tap), true);
|
expect(object.debugSemantics!.getSemanticsData().hasAction(SemanticsAction.tap), true);
|
||||||
|
|
||||||
semantics.dispose();
|
semantics.dispose();
|
||||||
SystemChannels.accessibility.setMockMessageHandler(null);
|
tester.binding.defaultBinaryMessenger.setMockDecodedMessageHandler<dynamic>(SystemChannels.accessibility, null);
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('Radio ink ripple is displayed correctly', (WidgetTester tester) async {
|
testWidgets('Radio ink ripple is displayed correctly', (WidgetTester tester) async {
|
||||||
|
@ -32,12 +32,12 @@ void main() {
|
|||||||
setUp(() async {
|
setUp(() async {
|
||||||
// Fill the clipboard so that the Paste option is available in the text
|
// Fill the clipboard so that the Paste option is available in the text
|
||||||
// selection menu.
|
// selection menu.
|
||||||
SystemChannels.platform.setMockMethodCallHandler(mockClipboard.handleMethodCall);
|
TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, mockClipboard.handleMethodCall);
|
||||||
await Clipboard.setData(const ClipboardData(text: 'Clipboard data'));
|
await Clipboard.setData(const ClipboardData(text: 'Clipboard data'));
|
||||||
});
|
});
|
||||||
|
|
||||||
tearDown(() {
|
tearDown(() {
|
||||||
SystemChannels.platform.setMockMethodCallHandler(null);
|
TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, null);
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('Can open and close search', (WidgetTester tester) async {
|
testWidgets('Can open and close search', (WidgetTester tester) async {
|
||||||
|
@ -577,7 +577,7 @@ void main() {
|
|||||||
testWidgets('switch has semantic events', (WidgetTester tester) async {
|
testWidgets('switch has semantic events', (WidgetTester tester) async {
|
||||||
dynamic semanticEvent;
|
dynamic semanticEvent;
|
||||||
bool value = false;
|
bool value = false;
|
||||||
SystemChannels.accessibility.setMockMessageHandler((dynamic message) async {
|
tester.binding.defaultBinaryMessenger.setMockDecodedMessageHandler<dynamic>(SystemChannels.accessibility, (dynamic message) async {
|
||||||
semanticEvent = message;
|
semanticEvent = message;
|
||||||
});
|
});
|
||||||
final SemanticsTester semanticsTester = SemanticsTester(tester);
|
final SemanticsTester semanticsTester = SemanticsTester(tester);
|
||||||
@ -615,13 +615,13 @@ void main() {
|
|||||||
expect(object.debugSemantics!.getSemanticsData().hasAction(SemanticsAction.tap), true);
|
expect(object.debugSemantics!.getSemanticsData().hasAction(SemanticsAction.tap), true);
|
||||||
|
|
||||||
semanticsTester.dispose();
|
semanticsTester.dispose();
|
||||||
SystemChannels.accessibility.setMockMessageHandler(null);
|
tester.binding.defaultBinaryMessenger.setMockDecodedMessageHandler<dynamic>(SystemChannels.accessibility, null);
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('switch sends semantic events from parent if fully merged', (WidgetTester tester) async {
|
testWidgets('switch sends semantic events from parent if fully merged', (WidgetTester tester) async {
|
||||||
dynamic semanticEvent;
|
dynamic semanticEvent;
|
||||||
bool value = false;
|
bool value = false;
|
||||||
SystemChannels.accessibility.setMockMessageHandler((dynamic message) async {
|
tester.binding.defaultBinaryMessenger.setMockDecodedMessageHandler<dynamic>(SystemChannels.accessibility, (dynamic message) async {
|
||||||
semanticEvent = message;
|
semanticEvent = message;
|
||||||
});
|
});
|
||||||
final SemanticsTester semanticsTester = SemanticsTester(tester);
|
final SemanticsTester semanticsTester = SemanticsTester(tester);
|
||||||
@ -665,7 +665,7 @@ void main() {
|
|||||||
expect(object.debugSemantics!.getSemanticsData().hasAction(SemanticsAction.tap), true);
|
expect(object.debugSemantics!.getSemanticsData().hasAction(SemanticsAction.tap), true);
|
||||||
|
|
||||||
semanticsTester.dispose();
|
semanticsTester.dispose();
|
||||||
SystemChannels.accessibility.setMockMessageHandler(null);
|
tester.binding.defaultBinaryMessenger.setMockDecodedMessageHandler<dynamic>(SystemChannels.accessibility, null);
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('Switch.adaptive', (WidgetTester tester) async {
|
testWidgets('Switch.adaptive', (WidgetTester tester) async {
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
import 'dart:async';
|
||||||
import 'dart:math' as math;
|
import 'dart:math' as math;
|
||||||
import 'dart:ui' as ui show window, BoxHeightStyle, BoxWidthStyle;
|
import 'dart:ui' as ui show window, BoxHeightStyle, BoxWidthStyle;
|
||||||
|
|
||||||
@ -164,14 +165,20 @@ void main() {
|
|||||||
|
|
||||||
setUp(() async {
|
setUp(() async {
|
||||||
debugResetSemanticsIdCounter();
|
debugResetSemanticsIdCounter();
|
||||||
SystemChannels.platform.setMockMethodCallHandler(mockClipboard.handleMethodCall);
|
TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMethodCallHandler(
|
||||||
|
SystemChannels.platform,
|
||||||
|
mockClipboard.handleMethodCall,
|
||||||
|
);
|
||||||
// Fill the clipboard so that the Paste option is available in the text
|
// Fill the clipboard so that the Paste option is available in the text
|
||||||
// selection menu.
|
// selection menu.
|
||||||
await Clipboard.setData(const ClipboardData(text: 'Clipboard data'));
|
await Clipboard.setData(const ClipboardData(text: 'Clipboard data'));
|
||||||
});
|
});
|
||||||
|
|
||||||
tearDown(() {
|
tearDown(() {
|
||||||
SystemChannels.platform.setMockMethodCallHandler(null);
|
TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMethodCallHandler(
|
||||||
|
SystemChannels.platform,
|
||||||
|
null,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
final Key textFieldKey = UniqueKey();
|
final Key textFieldKey = UniqueKey();
|
||||||
@ -339,7 +346,7 @@ void main() {
|
|||||||
|
|
||||||
testWidgets('TextField has consistent size', (WidgetTester tester) async {
|
testWidgets('TextField has consistent size', (WidgetTester tester) async {
|
||||||
final Key textFieldKey = UniqueKey();
|
final Key textFieldKey = UniqueKey();
|
||||||
late String textFieldValue;
|
String? textFieldValue;
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
overlay(
|
overlay(
|
||||||
@ -362,15 +369,16 @@ void main() {
|
|||||||
|
|
||||||
Future<void> checkText(String testValue) async {
|
Future<void> checkText(String testValue) async {
|
||||||
return TestAsyncUtils.guard(() async {
|
return TestAsyncUtils.guard(() async {
|
||||||
|
expect(textFieldValue, isNull);
|
||||||
await tester.enterText(find.byType(TextField), testValue);
|
await tester.enterText(find.byType(TextField), testValue);
|
||||||
// Check that the onChanged event handler fired.
|
// Check that the onChanged event handler fired.
|
||||||
expect(textFieldValue, equals(testValue));
|
expect(textFieldValue, equals(testValue));
|
||||||
|
textFieldValue = null;
|
||||||
await skipPastScrollingAnimation(tester);
|
await skipPastScrollingAnimation(tester);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
await checkText(' ');
|
await checkText(' ');
|
||||||
|
|
||||||
expect(findTextFieldBox(), equals(inputBox));
|
expect(findTextFieldBox(), equals(inputBox));
|
||||||
expect(inputBox.size, equals(emptyInputSize));
|
expect(inputBox.size, equals(emptyInputSize));
|
||||||
|
|
||||||
@ -416,6 +424,8 @@ void main() {
|
|||||||
text: 'X',
|
text: 'X',
|
||||||
selection: TextSelection.collapsed(offset: 1),
|
selection: TextSelection.collapsed(offset: 1),
|
||||||
));
|
));
|
||||||
|
await tester.idle();
|
||||||
|
expect(tester.state(find.byType(EditableText)), editableText);
|
||||||
await checkCursorToggle();
|
await checkCursorToggle();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -4694,8 +4704,8 @@ void main() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
String clipboardContent = '';
|
String clipboardContent = '';
|
||||||
SystemChannels.platform
|
tester.binding.defaultBinaryMessenger
|
||||||
.setMockMethodCallHandler((MethodCall methodCall) async {
|
.setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async {
|
||||||
if (methodCall.method == 'Clipboard.setData')
|
if (methodCall.method == 'Clipboard.setData')
|
||||||
clipboardContent = methodCall.arguments['text'] as String;
|
clipboardContent = methodCall.arguments['text'] as String;
|
||||||
else if (methodCall.method == 'Clipboard.getData')
|
else if (methodCall.method == 'Clipboard.getData')
|
||||||
@ -4767,8 +4777,8 @@ void main() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
String clipboardContent = '';
|
String clipboardContent = '';
|
||||||
SystemChannels.platform
|
tester.binding.defaultBinaryMessenger
|
||||||
.setMockMethodCallHandler((MethodCall methodCall) async {
|
.setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async {
|
||||||
if (methodCall.method == 'Clipboard.setData')
|
if (methodCall.method == 'Clipboard.setData')
|
||||||
clipboardContent = methodCall.arguments['text'] as String;
|
clipboardContent = methodCall.arguments['text'] as String;
|
||||||
else if (methodCall.method == 'Clipboard.getData')
|
else if (methodCall.method == 'Clipboard.getData')
|
||||||
@ -4840,8 +4850,8 @@ void main() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const String clipboardContent = 'I love Flutter!';
|
const String clipboardContent = 'I love Flutter!';
|
||||||
SystemChannels.platform
|
tester.binding.defaultBinaryMessenger
|
||||||
.setMockMethodCallHandler((MethodCall methodCall) async {
|
.setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async {
|
||||||
if (methodCall.method == 'Clipboard.getData')
|
if (methodCall.method == 'Clipboard.getData')
|
||||||
return <String, dynamic>{'text': clipboardContent};
|
return <String, dynamic>{'text': clipboardContent};
|
||||||
return null;
|
return null;
|
||||||
@ -4890,8 +4900,8 @@ void main() {
|
|||||||
maxLines: 3,
|
maxLines: 3,
|
||||||
);
|
);
|
||||||
String clipboardContent = '';
|
String clipboardContent = '';
|
||||||
SystemChannels.platform
|
tester.binding.defaultBinaryMessenger
|
||||||
.setMockMethodCallHandler((MethodCall methodCall) async {
|
.setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async {
|
||||||
if (methodCall.method == 'Clipboard.setData')
|
if (methodCall.method == 'Clipboard.setData')
|
||||||
clipboardContent = methodCall.arguments['text'] as String;
|
clipboardContent = methodCall.arguments['text'] as String;
|
||||||
else if (methodCall.method == 'Clipboard.getData')
|
else if (methodCall.method == 'Clipboard.getData')
|
||||||
@ -4964,8 +4974,8 @@ void main() {
|
|||||||
obscureText: true,
|
obscureText: true,
|
||||||
);
|
);
|
||||||
String clipboardContent = '';
|
String clipboardContent = '';
|
||||||
SystemChannels.platform
|
tester.binding.defaultBinaryMessenger
|
||||||
.setMockMethodCallHandler((MethodCall methodCall) async {
|
.setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async {
|
||||||
if (methodCall.method == 'Clipboard.setData')
|
if (methodCall.method == 'Clipboard.setData')
|
||||||
clipboardContent = methodCall.arguments['text'] as String;
|
clipboardContent = methodCall.arguments['text'] as String;
|
||||||
else if (methodCall.method == 'Clipboard.getData')
|
else if (methodCall.method == 'Clipboard.getData')
|
||||||
@ -9371,8 +9381,8 @@ void main() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
bool triedToReadClipboard = false;
|
bool triedToReadClipboard = false;
|
||||||
SystemChannels.platform
|
tester.binding.defaultBinaryMessenger
|
||||||
.setMockMethodCallHandler((MethodCall methodCall) async {
|
.setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async {
|
||||||
if (methodCall.method == 'Clipboard.getData') {
|
if (methodCall.method == 'Clipboard.getData') {
|
||||||
triedToReadClipboard = true;
|
triedToReadClipboard = true;
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@ class MockClipboard {
|
|||||||
void main() {
|
void main() {
|
||||||
TestWidgetsFlutterBinding.ensureInitialized();
|
TestWidgetsFlutterBinding.ensureInitialized();
|
||||||
final MockClipboard mockClipboard = MockClipboard();
|
final MockClipboard mockClipboard = MockClipboard();
|
||||||
SystemChannels.platform.setMockMethodCallHandler(mockClipboard.handleMethodCall);
|
TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, mockClipboard.handleMethodCall);
|
||||||
|
|
||||||
setUp(() async {
|
setUp(() async {
|
||||||
// Fill the clipboard so that the Paste option is available in the text
|
// Fill the clipboard so that the Paste option is available in the text
|
||||||
|
@ -28,7 +28,7 @@ class MockClipboard {
|
|||||||
void main() {
|
void main() {
|
||||||
TestWidgetsFlutterBinding.ensureInitialized();
|
TestWidgetsFlutterBinding.ensureInitialized();
|
||||||
final MockClipboard mockClipboard = MockClipboard();
|
final MockClipboard mockClipboard = MockClipboard();
|
||||||
SystemChannels.platform.setMockMethodCallHandler(mockClipboard.handleMethodCall);
|
TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, mockClipboard.handleMethodCall);
|
||||||
|
|
||||||
setUp(() async {
|
setUp(() async {
|
||||||
await Clipboard.setData(const ClipboardData(text: 'clipboard data'));
|
await Clipboard.setData(const ClipboardData(text: 'clipboard data'));
|
||||||
|
@ -1193,7 +1193,7 @@ void main() {
|
|||||||
|
|
||||||
testWidgets('has semantic events', (WidgetTester tester) async {
|
testWidgets('has semantic events', (WidgetTester tester) async {
|
||||||
final List<dynamic> semanticEvents = <dynamic>[];
|
final List<dynamic> semanticEvents = <dynamic>[];
|
||||||
SystemChannels.accessibility.setMockMessageHandler((dynamic message) async {
|
tester.binding.defaultBinaryMessenger.setMockDecodedMessageHandler<dynamic>(SystemChannels.accessibility, (dynamic message) async {
|
||||||
semanticEvents.add(message);
|
semanticEvents.add(message);
|
||||||
});
|
});
|
||||||
final SemanticsTester semantics = SemanticsTester(tester);
|
final SemanticsTester semantics = SemanticsTester(tester);
|
||||||
@ -1230,7 +1230,7 @@ void main() {
|
|||||||
},
|
},
|
||||||
]));
|
]));
|
||||||
semantics.dispose();
|
semantics.dispose();
|
||||||
SystemChannels.accessibility.setMockMessageHandler(null);
|
tester.binding.defaultBinaryMessenger.setMockDecodedMessageHandler<dynamic>(SystemChannels.accessibility, null);
|
||||||
});
|
});
|
||||||
testWidgets('default Tooltip debugFillProperties', (WidgetTester tester) async {
|
testWidgets('default Tooltip debugFillProperties', (WidgetTester tester) async {
|
||||||
final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder();
|
final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder();
|
||||||
|
@ -1153,7 +1153,7 @@ void main() {
|
|||||||
|
|
||||||
testWidgets('has semantic events by default - ThemeData.tooltipTheme', (WidgetTester tester) async {
|
testWidgets('has semantic events by default - ThemeData.tooltipTheme', (WidgetTester tester) async {
|
||||||
final List<dynamic> semanticEvents = <dynamic>[];
|
final List<dynamic> semanticEvents = <dynamic>[];
|
||||||
SystemChannels.accessibility.setMockMessageHandler((dynamic message) async {
|
tester.binding.defaultBinaryMessenger.setMockDecodedMessageHandler<dynamic>(SystemChannels.accessibility, (dynamic message) async {
|
||||||
semanticEvents.add(message);
|
semanticEvents.add(message);
|
||||||
});
|
});
|
||||||
final SemanticsTester semantics = SemanticsTester(tester);
|
final SemanticsTester semantics = SemanticsTester(tester);
|
||||||
@ -1191,12 +1191,12 @@ void main() {
|
|||||||
},
|
},
|
||||||
]));
|
]));
|
||||||
semantics.dispose();
|
semantics.dispose();
|
||||||
SystemChannels.accessibility.setMockMessageHandler(null);
|
tester.binding.defaultBinaryMessenger.setMockDecodedMessageHandler<dynamic>(SystemChannels.accessibility, null);
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('has semantic events by default - TooltipTheme', (WidgetTester tester) async {
|
testWidgets('has semantic events by default - TooltipTheme', (WidgetTester tester) async {
|
||||||
final List<dynamic> semanticEvents = <dynamic>[];
|
final List<dynamic> semanticEvents = <dynamic>[];
|
||||||
SystemChannels.accessibility.setMockMessageHandler((dynamic message) async {
|
tester.binding.defaultBinaryMessenger.setMockDecodedMessageHandler<dynamic>(SystemChannels.accessibility, (dynamic message) async {
|
||||||
semanticEvents.add(message);
|
semanticEvents.add(message);
|
||||||
});
|
});
|
||||||
final SemanticsTester semantics = SemanticsTester(tester);
|
final SemanticsTester semantics = SemanticsTester(tester);
|
||||||
@ -1236,7 +1236,7 @@ void main() {
|
|||||||
},
|
},
|
||||||
]));
|
]));
|
||||||
semantics.dispose();
|
semantics.dispose();
|
||||||
SystemChannels.accessibility.setMockMessageHandler(null);
|
tester.binding.defaultBinaryMessenger.setMockDecodedMessageHandler<dynamic>(SystemChannels.accessibility, null);
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('default Tooltip debugFillProperties', (WidgetTester tester) async {
|
testWidgets('default Tooltip debugFillProperties', (WidgetTester tester) async {
|
||||||
|
@ -12,11 +12,11 @@ import 'package:flutter/services.dart';
|
|||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
final TestRenderBinding binding = TestRenderBinding();
|
||||||
test('Flutter dispatches first frame event on the web only', () async {
|
test('Flutter dispatches first frame event on the web only', () async {
|
||||||
final Completer<void> completer = Completer<void>();
|
final Completer<void> completer = Completer<void>();
|
||||||
final TestRenderBinding binding = TestRenderBinding();
|
|
||||||
const MethodChannel firstFrameChannel = MethodChannel('flutter/service_worker');
|
const MethodChannel firstFrameChannel = MethodChannel('flutter/service_worker');
|
||||||
firstFrameChannel.setMockMethodCallHandler((MethodCall methodCall) async {
|
binding.defaultBinaryMessenger.setMockMethodCallHandler(firstFrameChannel, (MethodCall methodCall) async {
|
||||||
completer.complete();
|
completer.complete();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -27,4 +27,10 @@ void main() {
|
|||||||
}, skip: !kIsWeb);
|
}, skip: !kIsWeb);
|
||||||
}
|
}
|
||||||
|
|
||||||
class TestRenderBinding extends BindingBase with SchedulerBinding, ServicesBinding, GestureBinding, SemanticsBinding, RendererBinding {}
|
class TestRenderBinding extends BindingBase
|
||||||
|
with SchedulerBinding,
|
||||||
|
ServicesBinding,
|
||||||
|
GestureBinding,
|
||||||
|
SemanticsBinding,
|
||||||
|
RendererBinding,
|
||||||
|
TestDefaultBinaryMessengerBinding { }
|
||||||
|
@ -56,14 +56,14 @@ void main() {
|
|||||||
|
|
||||||
setUp(() {
|
setUp(() {
|
||||||
_binding.postFrameCallbacks.clear();
|
_binding.postFrameCallbacks.clear();
|
||||||
SystemChannels.mouseCursor.setMockMethodCallHandler((MethodCall call) async {
|
_binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.mouseCursor, (MethodCall call) async {
|
||||||
if (_methodCallHandler != null)
|
if (_methodCallHandler != null)
|
||||||
return _methodCallHandler!(call);
|
return _methodCallHandler!(call);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
tearDown(() {
|
tearDown(() {
|
||||||
SystemChannels.mouseCursor.setMockMethodCallHandler(null);
|
_binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.mouseCursor, null);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Should work on platforms that does not support mouse cursor', () async {
|
test('Should work on platforms that does not support mouse cursor', () async {
|
||||||
|
@ -9,6 +9,7 @@ import 'package:flutter/gestures.dart';
|
|||||||
import 'package:flutter/rendering.dart';
|
import 'package:flutter/rendering.dart';
|
||||||
import 'package:flutter/scheduler.dart';
|
import 'package:flutter/scheduler.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:flutter_test/flutter_test.dart' show TestDefaultBinaryMessengerBinding;
|
||||||
|
|
||||||
class _TestHitTester extends RenderBox {
|
class _TestHitTester extends RenderBox {
|
||||||
_TestHitTester(this.hitTestOverride);
|
_TestHitTester(this.hitTestOverride);
|
||||||
@ -24,7 +25,7 @@ class _TestHitTester extends RenderBox {
|
|||||||
// A binding used to test MouseTracker, allowing the test to override hit test
|
// A binding used to test MouseTracker, allowing the test to override hit test
|
||||||
// searching.
|
// searching.
|
||||||
class TestMouseTrackerFlutterBinding extends BindingBase
|
class TestMouseTrackerFlutterBinding extends BindingBase
|
||||||
with SchedulerBinding, ServicesBinding, GestureBinding, SemanticsBinding, RendererBinding {
|
with SchedulerBinding, ServicesBinding, GestureBinding, SemanticsBinding, RendererBinding, TestDefaultBinaryMessengerBinding {
|
||||||
@override
|
@override
|
||||||
void initInstances() {
|
void initInstances() {
|
||||||
super.initInstances();
|
super.initInstances();
|
||||||
|
@ -9,12 +9,12 @@ import 'package:flutter/gestures.dart';
|
|||||||
import 'package:flutter/rendering.dart';
|
import 'package:flutter/rendering.dart';
|
||||||
import 'package:flutter/scheduler.dart';
|
import 'package:flutter/scheduler.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_test/flutter_test.dart' show EnginePhase, fail;
|
import 'package:flutter_test/flutter_test.dart' show TestDefaultBinaryMessengerBinding, EnginePhase, fail;
|
||||||
|
|
||||||
export 'package:flutter/foundation.dart' show FlutterError, FlutterErrorDetails;
|
export 'package:flutter/foundation.dart' show FlutterError, FlutterErrorDetails;
|
||||||
export 'package:flutter_test/flutter_test.dart' show EnginePhase;
|
export 'package:flutter_test/flutter_test.dart' show TestDefaultBinaryMessengerBinding, EnginePhase;
|
||||||
|
|
||||||
class TestRenderingFlutterBinding extends BindingBase with SchedulerBinding, ServicesBinding, GestureBinding, PaintingBinding, SemanticsBinding, RendererBinding {
|
class TestRenderingFlutterBinding extends BindingBase with SchedulerBinding, ServicesBinding, GestureBinding, PaintingBinding, SemanticsBinding, RendererBinding, TestDefaultBinaryMessengerBinding {
|
||||||
/// Creates a binding for testing rendering library functionality.
|
/// Creates a binding for testing rendering library functionality.
|
||||||
///
|
///
|
||||||
/// If [onErrors] is not null, it is called if [FlutterError] caught any errors
|
/// If [onErrors] is not null, it is called if [FlutterError] caught any errors
|
||||||
|
@ -13,12 +13,13 @@ void main() {
|
|||||||
|
|
||||||
test('Semantic announcement', () async {
|
test('Semantic announcement', () async {
|
||||||
final List<Map<dynamic, dynamic>> log = <Map<dynamic, dynamic>>[];
|
final List<Map<dynamic, dynamic>> log = <Map<dynamic, dynamic>>[];
|
||||||
|
|
||||||
Future<dynamic> handleMessage(dynamic mockMessage) async {
|
Future<dynamic> handleMessage(dynamic mockMessage) async {
|
||||||
final Map<dynamic, dynamic> message = mockMessage as Map<dynamic, dynamic>;
|
final Map<dynamic, dynamic> message = mockMessage as Map<dynamic, dynamic>;
|
||||||
log.add(message);
|
log.add(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
SystemChannels.accessibility.setMockMessageHandler(handleMessage);
|
TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockDecodedMessageHandler<dynamic>(SystemChannels.accessibility, handleMessage);
|
||||||
|
|
||||||
await SemanticsService.announce('announcement 1', TextDirection.ltr);
|
await SemanticsService.announce('announcement 1', TextDirection.ltr);
|
||||||
await SemanticsService.announce('announcement 2', TextDirection.rtl);
|
await SemanticsService.announce('announcement 2', TextDirection.rtl);
|
||||||
|
@ -191,15 +191,6 @@ class FakeTextChannel implements MethodChannel {
|
|||||||
incoming = handler;
|
incoming = handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
bool checkMethodCallHandler(Future<void> Function(MethodCall call)? handler) => throw UnimplementedError();
|
|
||||||
|
|
||||||
@override
|
|
||||||
void setMockMethodCallHandler(Future<void>? Function(MethodCall call)? handler) => throw UnimplementedError();
|
|
||||||
|
|
||||||
@override
|
|
||||||
bool checkMockMethodCallHandler(Future<void> Function(MethodCall call)? handler) => throw UnimplementedError();
|
|
||||||
|
|
||||||
void validateOutgoingMethodCalls(List<MethodCall> calls) {
|
void validateOutgoingMethodCalls(List<MethodCall> calls) {
|
||||||
expect(outgoingCalls.length, calls.length);
|
expect(outgoingCalls.length, calls.length);
|
||||||
bool hasError = false;
|
bool hasError = false;
|
||||||
|
@ -34,7 +34,7 @@ L2Paragraph2
|
|||||||
|
|
||||||
L2Paragraph3''';
|
L2Paragraph3''';
|
||||||
|
|
||||||
const String licenses = '''
|
const String combinedLicenses = '''
|
||||||
$license1
|
$license1
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
$license2
|
$license2
|
||||||
@ -42,29 +42,25 @@ $license2
|
|||||||
|
|
||||||
class TestBinding extends BindingBase with SchedulerBinding, ServicesBinding {
|
class TestBinding extends BindingBase with SchedulerBinding, ServicesBinding {
|
||||||
@override
|
@override
|
||||||
BinaryMessenger createBinaryMessenger() {
|
TestDefaultBinaryMessenger get defaultBinaryMessenger => super.defaultBinaryMessenger as TestDefaultBinaryMessenger;
|
||||||
return super.createBinaryMessenger()
|
|
||||||
..setMockMessageHandler('flutter/assets', (ByteData? message) async {
|
@override
|
||||||
if (const StringCodec().decodeMessage(message) == 'NOTICES') {
|
TestDefaultBinaryMessenger createBinaryMessenger() {
|
||||||
return const StringCodec().encodeMessage(licenses);
|
return TestDefaultBinaryMessenger(super.createBinaryMessenger());
|
||||||
}
|
|
||||||
return null;
|
|
||||||
})
|
|
||||||
..setMockMessageHandler('flutter/assets', (ByteData? message) async {
|
|
||||||
if (const StringCodec().decodeMessage(message) == 'NOTICES.Z' && !kIsWeb) {
|
|
||||||
return Uint8List.fromList(gzip.encode(utf8.encode(licenses))).buffer.asByteData();
|
|
||||||
}
|
|
||||||
if (const StringCodec().decodeMessage(message) == 'NOTICES' && kIsWeb) {
|
|
||||||
return const StringCodec().encodeMessage(licenses);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
test('Adds rootBundle LICENSES to LicenseRegistry', () async {
|
test('Adds rootBundle LICENSES to LicenseRegistry', () async {
|
||||||
TestBinding(); // The test binding registers a mock handler that returns licenses for the LICENSE key
|
TestBinding().defaultBinaryMessenger.setMockMessageHandler('flutter/assets', (ByteData? message) async {
|
||||||
|
if (const StringCodec().decodeMessage(message) == 'NOTICES.Z' && !kIsWeb) {
|
||||||
|
return Uint8List.fromList(gzip.encode(utf8.encode(combinedLicenses))).buffer.asByteData();
|
||||||
|
}
|
||||||
|
if (const StringCodec().decodeMessage(message) == 'NOTICES' && kIsWeb) {
|
||||||
|
return const StringCodec().encodeMessage(combinedLicenses);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
|
||||||
final List<LicenseEntry> licenses = await LicenseRegistry.licenses.toList();
|
final List<LicenseEntry> licenses = await LicenseRegistry.licenses.toList();
|
||||||
|
|
||||||
|
@ -2,9 +2,10 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
import 'dart:async';
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:typed_data';
|
import 'dart:typed_data';
|
||||||
import 'dart:ui' as ui;
|
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
|
||||||
@ -19,36 +20,39 @@ void main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
test('default binary messenger calls callback once', () async {
|
test('default binary messenger calls callback once', () async {
|
||||||
int count = 0;
|
int countInbound = 0;
|
||||||
|
int countOutbound = 0;
|
||||||
const String channel = 'foo';
|
const String channel = 'foo';
|
||||||
ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage(
|
final ByteData bar = _makeByteData('bar');
|
||||||
|
final Completer<void> done = Completer<void>();
|
||||||
|
ServicesBinding.instance!.channelBuffers.push(
|
||||||
channel,
|
channel,
|
||||||
_makeByteData('bar'),
|
bar,
|
||||||
(ByteData? message) async {
|
(ByteData? message) async {
|
||||||
count += 1;
|
expect(message, isNull);
|
||||||
|
countOutbound += 1;
|
||||||
|
done.complete();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
expect(count, equals(0));
|
expect(countInbound, equals(0));
|
||||||
await ui.channelBuffers.drain(channel, (ByteData? data, ui.PlatformMessageResponseCallback callback) async {
|
expect(countOutbound, equals(0));
|
||||||
callback(null);
|
ServicesBinding.instance!.defaultBinaryMessenger.setMessageHandler(
|
||||||
});
|
channel,
|
||||||
expect(count, equals(1));
|
(ByteData? message) async {
|
||||||
});
|
expect(message, bar);
|
||||||
|
countInbound += 1;
|
||||||
test('can check the handler', () {
|
},
|
||||||
Future<ByteData> handler(ByteData? call) => Future<ByteData>.value(null);
|
);
|
||||||
final BinaryMessenger messenger = ServicesBinding.instance!.defaultBinaryMessenger;
|
expect(countInbound, equals(0));
|
||||||
|
expect(countOutbound, equals(0));
|
||||||
expect(messenger.checkMessageHandler('test_channel', null), true);
|
await done.future;
|
||||||
expect(messenger.checkMessageHandler('test_channel', handler), false);
|
expect(countInbound, equals(1));
|
||||||
messenger.setMessageHandler('test_channel', handler);
|
expect(countOutbound, equals(1));
|
||||||
expect(messenger.checkMessageHandler('test_channel', handler), true);
|
|
||||||
messenger.setMessageHandler('test_channel', null);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('can check the mock handler', () {
|
test('can check the mock handler', () {
|
||||||
Future<ByteData> handler(ByteData? call) => Future<ByteData>.value(null);
|
Future<ByteData> handler(ByteData? call) => Future<ByteData>.value(null);
|
||||||
final BinaryMessenger messenger = ServicesBinding.instance!.defaultBinaryMessenger;
|
final TestDefaultBinaryMessenger messenger = TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger;
|
||||||
|
|
||||||
expect(messenger.checkMockMessageHandler('test_channel', null), true);
|
expect(messenger.checkMockMessageHandler('test_channel', null), true);
|
||||||
expect(messenger.checkMockMessageHandler('test_channel', handler), false);
|
expect(messenger.checkMockMessageHandler('test_channel', handler), false);
|
||||||
|
@ -11,7 +11,7 @@ void main() {
|
|||||||
test('installDeferredComponent test', () async {
|
test('installDeferredComponent test', () async {
|
||||||
final List<MethodCall> log = <MethodCall>[];
|
final List<MethodCall> log = <MethodCall>[];
|
||||||
|
|
||||||
SystemChannels.deferredComponent.setMockMethodCallHandler((MethodCall methodCall) async {
|
TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.deferredComponent, (MethodCall methodCall) async {
|
||||||
log.add(methodCall);
|
log.add(methodCall);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -27,7 +27,7 @@ void main() {
|
|||||||
test('uninstallDeferredComponent test', () async {
|
test('uninstallDeferredComponent test', () async {
|
||||||
final List<MethodCall> log = <MethodCall>[];
|
final List<MethodCall> log = <MethodCall>[];
|
||||||
|
|
||||||
SystemChannels.deferredComponent.setMockMethodCallHandler((MethodCall methodCall) async {
|
TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.deferredComponent, (MethodCall methodCall) async {
|
||||||
log.add(methodCall);
|
log.add(methodCall);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@ import 'dart:typed_data';
|
|||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
|
||||||
/// Used in internal testing.
|
/// Used in internal testing.
|
||||||
class FakePlatformViewController extends PlatformViewController {
|
class FakePlatformViewController extends PlatformViewController {
|
||||||
@ -122,7 +123,7 @@ class FakeAndroidViewController implements AndroidViewController {
|
|||||||
|
|
||||||
class FakeAndroidPlatformViewsController {
|
class FakeAndroidPlatformViewsController {
|
||||||
FakeAndroidPlatformViewsController() {
|
FakeAndroidPlatformViewsController() {
|
||||||
SystemChannels.platform_views.setMockMethodCallHandler(_onMethodCall);
|
TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform_views, _onMethodCall);
|
||||||
}
|
}
|
||||||
|
|
||||||
Iterable<FakeAndroidPlatformView> get views => _views.values;
|
Iterable<FakeAndroidPlatformView> get views => _views.values;
|
||||||
@ -301,7 +302,7 @@ class FakeAndroidPlatformViewsController {
|
|||||||
|
|
||||||
class FakeIosPlatformViewsController {
|
class FakeIosPlatformViewsController {
|
||||||
FakeIosPlatformViewsController() {
|
FakeIosPlatformViewsController() {
|
||||||
SystemChannels.platform_views.setMockMethodCallHandler(_onMethodCall);
|
TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform_views, _onMethodCall);
|
||||||
}
|
}
|
||||||
|
|
||||||
Iterable<FakeUiKitView> get views => _views.values;
|
Iterable<FakeUiKitView> get views => _views.values;
|
||||||
@ -396,7 +397,7 @@ class FakeIosPlatformViewsController {
|
|||||||
|
|
||||||
class FakeHtmlPlatformViewsController {
|
class FakeHtmlPlatformViewsController {
|
||||||
FakeHtmlPlatformViewsController() {
|
FakeHtmlPlatformViewsController() {
|
||||||
SystemChannels.platform_views.setMockMethodCallHandler(_onMethodCall);
|
TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform_views, _onMethodCall);
|
||||||
}
|
}
|
||||||
|
|
||||||
Iterable<FakeHtmlPlatformView> get views => _views.values;
|
Iterable<FakeHtmlPlatformView> get views => _views.values;
|
||||||
|
@ -11,7 +11,7 @@ void main() {
|
|||||||
test('Haptic feedback control test', () async {
|
test('Haptic feedback control test', () async {
|
||||||
final List<MethodCall> log = <MethodCall>[];
|
final List<MethodCall> log = <MethodCall>[];
|
||||||
|
|
||||||
SystemChannels.platform.setMockMethodCallHandler((MethodCall methodCall) async {
|
TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async {
|
||||||
log.add(methodCall);
|
log.add(methodCall);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -25,7 +25,7 @@ void main() {
|
|||||||
Future<void> callAndVerifyHapticFunction(Function hapticFunction, String platformMethodArgument) async {
|
Future<void> callAndVerifyHapticFunction(Function hapticFunction, String platformMethodArgument) async {
|
||||||
final List<MethodCall> log = <MethodCall>[];
|
final List<MethodCall> log = <MethodCall>[];
|
||||||
|
|
||||||
SystemChannels.platform.setMockMethodCallHandler((MethodCall methodCall) async {
|
TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async {
|
||||||
log.add(methodCall);
|
log.add(methodCall);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ void main() {
|
|||||||
const MessageCodec<String?> string = StringCodec();
|
const MessageCodec<String?> string = StringCodec();
|
||||||
const BasicMessageChannel<String?> channel = BasicMessageChannel<String?>('ch', string);
|
const BasicMessageChannel<String?> channel = BasicMessageChannel<String?>('ch', string);
|
||||||
test('can send string message and get reply', () async {
|
test('can send string message and get reply', () async {
|
||||||
ServicesBinding.instance!.defaultBinaryMessenger.setMockMessageHandler(
|
TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMessageHandler(
|
||||||
'ch',
|
'ch',
|
||||||
(ByteData? message) async => string.encodeMessage(string.decodeMessage(message)! + ' world'),
|
(ByteData? message) async => string.encodeMessage(string.decodeMessage(message)! + ' world'),
|
||||||
);
|
);
|
||||||
@ -23,7 +23,7 @@ void main() {
|
|||||||
test('can receive string message and send reply', () async {
|
test('can receive string message and send reply', () async {
|
||||||
channel.setMessageHandler((String? message) async => message! + ' world');
|
channel.setMessageHandler((String? message) async => message! + ' world');
|
||||||
String? reply;
|
String? reply;
|
||||||
await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage(
|
await TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.handlePlatformMessage(
|
||||||
'ch',
|
'ch',
|
||||||
const StringCodec().encodeMessage('hello'),
|
const StringCodec().encodeMessage('hello'),
|
||||||
(ByteData? replyBinary) {
|
(ByteData? replyBinary) {
|
||||||
@ -40,7 +40,7 @@ void main() {
|
|||||||
const MethodChannel channel = MethodChannel('ch7', jsonMethod);
|
const MethodChannel channel = MethodChannel('ch7', jsonMethod);
|
||||||
const OptionalMethodChannel optionalMethodChannel = OptionalMethodChannel('ch8', jsonMethod);
|
const OptionalMethodChannel optionalMethodChannel = OptionalMethodChannel('ch8', jsonMethod);
|
||||||
test('can invoke method and get result', () async {
|
test('can invoke method and get result', () async {
|
||||||
ServicesBinding.instance!.defaultBinaryMessenger.setMockMessageHandler(
|
TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMessageHandler(
|
||||||
'ch7',
|
'ch7',
|
||||||
(ByteData? message) async {
|
(ByteData? message) async {
|
||||||
final Map<dynamic, dynamic> methodCall = jsonMessage.decodeMessage(message) as Map<dynamic, dynamic>;
|
final Map<dynamic, dynamic> methodCall = jsonMessage.decodeMessage(message) as Map<dynamic, dynamic>;
|
||||||
@ -56,7 +56,7 @@ void main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('can invoke list method and get result', () async {
|
test('can invoke list method and get result', () async {
|
||||||
ServicesBinding.instance!.defaultBinaryMessenger.setMockMessageHandler(
|
TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMessageHandler(
|
||||||
'ch7',
|
'ch7',
|
||||||
(ByteData? message) async {
|
(ByteData? message) async {
|
||||||
final Map<dynamic, dynamic> methodCall = jsonMessage.decodeMessage(message) as Map<dynamic, dynamic>;
|
final Map<dynamic, dynamic> methodCall = jsonMessage.decodeMessage(message) as Map<dynamic, dynamic>;
|
||||||
@ -72,7 +72,7 @@ void main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('can invoke list method and get null result', () async {
|
test('can invoke list method and get null result', () async {
|
||||||
ServicesBinding.instance!.defaultBinaryMessenger.setMockMessageHandler(
|
TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMessageHandler(
|
||||||
'ch7',
|
'ch7',
|
||||||
(ByteData? message) async {
|
(ByteData? message) async {
|
||||||
final Map<dynamic, dynamic> methodCall = jsonMessage.decodeMessage(message) as Map<dynamic, dynamic>;
|
final Map<dynamic, dynamic> methodCall = jsonMessage.decodeMessage(message) as Map<dynamic, dynamic>;
|
||||||
@ -87,7 +87,7 @@ void main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('can invoke map method and get result', () async {
|
test('can invoke map method and get result', () async {
|
||||||
ServicesBinding.instance!.defaultBinaryMessenger.setMockMessageHandler(
|
TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMessageHandler(
|
||||||
'ch7',
|
'ch7',
|
||||||
(ByteData? message) async {
|
(ByteData? message) async {
|
||||||
final Map<dynamic, dynamic> methodCall = jsonMessage.decodeMessage(message) as Map<dynamic, dynamic>;
|
final Map<dynamic, dynamic> methodCall = jsonMessage.decodeMessage(message) as Map<dynamic, dynamic>;
|
||||||
@ -103,7 +103,7 @@ void main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('can invoke map method and get null result', () async {
|
test('can invoke map method and get null result', () async {
|
||||||
ServicesBinding.instance!.defaultBinaryMessenger.setMockMessageHandler(
|
TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMessageHandler(
|
||||||
'ch7',
|
'ch7',
|
||||||
(ByteData? message) async {
|
(ByteData? message) async {
|
||||||
final Map<dynamic, dynamic> methodCall = jsonMessage.decodeMessage(message) as Map<dynamic, dynamic>;
|
final Map<dynamic, dynamic> methodCall = jsonMessage.decodeMessage(message) as Map<dynamic, dynamic>;
|
||||||
@ -118,7 +118,7 @@ void main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('can invoke method and get error', () async {
|
test('can invoke method and get error', () async {
|
||||||
ServicesBinding.instance!.defaultBinaryMessenger.setMockMessageHandler(
|
TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMessageHandler(
|
||||||
'ch7',
|
'ch7',
|
||||||
(ByteData? message) async {
|
(ByteData? message) async {
|
||||||
return jsonMessage.encodeMessage(<dynamic>[
|
return jsonMessage.encodeMessage(<dynamic>[
|
||||||
@ -141,7 +141,7 @@ void main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('can invoke unimplemented method', () async {
|
test('can invoke unimplemented method', () async {
|
||||||
ServicesBinding.instance!.defaultBinaryMessenger.setMockMessageHandler(
|
TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMessageHandler(
|
||||||
'ch7',
|
'ch7',
|
||||||
(ByteData? message) async => null,
|
(ByteData? message) async => null,
|
||||||
);
|
);
|
||||||
@ -157,7 +157,7 @@ void main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('can invoke unimplemented method (optional)', () async {
|
test('can invoke unimplemented method (optional)', () async {
|
||||||
ServicesBinding.instance!.defaultBinaryMessenger.setMockMessageHandler(
|
TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMessageHandler(
|
||||||
'ch8',
|
'ch8',
|
||||||
(ByteData? message) async => null,
|
(ByteData? message) async => null,
|
||||||
);
|
);
|
||||||
@ -169,7 +169,7 @@ void main() {
|
|||||||
channel.setMethodCallHandler(null);
|
channel.setMethodCallHandler(null);
|
||||||
final ByteData call = jsonMethod.encodeMethodCall(const MethodCall('sayHello', 'hello'));
|
final ByteData call = jsonMethod.encodeMethodCall(const MethodCall('sayHello', 'hello'));
|
||||||
ByteData? envelope;
|
ByteData? envelope;
|
||||||
await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage('ch7', call, (ByteData? result) {
|
await TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.handlePlatformMessage('ch7', call, (ByteData? result) {
|
||||||
envelope = result;
|
envelope = result;
|
||||||
});
|
});
|
||||||
await null; // just in case there's something async happening
|
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 {
|
test('can handle method call with no registered plugin (setting after)', () async {
|
||||||
final ByteData call = jsonMethod.encodeMethodCall(const MethodCall('sayHello', 'hello'));
|
final ByteData call = jsonMethod.encodeMethodCall(const MethodCall('sayHello', 'hello'));
|
||||||
ByteData? envelope;
|
ByteData? envelope;
|
||||||
await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage('ch7', call, (ByteData? result) {
|
await TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.handlePlatformMessage('ch7', call, (ByteData? result) {
|
||||||
envelope = result;
|
envelope = result;
|
||||||
});
|
});
|
||||||
channel.setMethodCallHandler(null);
|
channel.setMethodCallHandler(null);
|
||||||
@ -193,7 +193,7 @@ void main() {
|
|||||||
});
|
});
|
||||||
final ByteData call = jsonMethod.encodeMethodCall(const MethodCall('sayHello', 'hello'));
|
final ByteData call = jsonMethod.encodeMethodCall(const MethodCall('sayHello', 'hello'));
|
||||||
ByteData? envelope;
|
ByteData? envelope;
|
||||||
await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage('ch7', call, (ByteData? result) {
|
await TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.handlePlatformMessage('ch7', call, (ByteData? result) {
|
||||||
envelope = result;
|
envelope = result;
|
||||||
});
|
});
|
||||||
expect(envelope, isNull);
|
expect(envelope, isNull);
|
||||||
@ -203,7 +203,7 @@ void main() {
|
|||||||
channel.setMethodCallHandler((MethodCall call) async => '${call.arguments}, world');
|
channel.setMethodCallHandler((MethodCall call) async => '${call.arguments}, world');
|
||||||
final ByteData call = jsonMethod.encodeMethodCall(const MethodCall('sayHello', 'hello'));
|
final ByteData call = jsonMethod.encodeMethodCall(const MethodCall('sayHello', 'hello'));
|
||||||
ByteData? envelope;
|
ByteData? envelope;
|
||||||
await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage('ch7', call, (ByteData? result) {
|
await TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.handlePlatformMessage('ch7', call, (ByteData? result) {
|
||||||
envelope = result;
|
envelope = result;
|
||||||
});
|
});
|
||||||
expect(jsonMethod.decodeEnvelope(envelope!), equals('hello, world'));
|
expect(jsonMethod.decodeEnvelope(envelope!), equals('hello, world'));
|
||||||
@ -215,7 +215,7 @@ void main() {
|
|||||||
});
|
});
|
||||||
final ByteData call = jsonMethod.encodeMethodCall(const MethodCall('sayHello', 'hello'));
|
final ByteData call = jsonMethod.encodeMethodCall(const MethodCall('sayHello', 'hello'));
|
||||||
ByteData? envelope;
|
ByteData? envelope;
|
||||||
await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage('ch7', call, (ByteData? result) {
|
await TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.handlePlatformMessage('ch7', call, (ByteData? result) {
|
||||||
envelope = result;
|
envelope = result;
|
||||||
});
|
});
|
||||||
try {
|
try {
|
||||||
@ -235,7 +235,7 @@ void main() {
|
|||||||
});
|
});
|
||||||
final ByteData call = jsonMethod.encodeMethodCall(const MethodCall('sayHello', 'hello'));
|
final ByteData call = jsonMethod.encodeMethodCall(const MethodCall('sayHello', 'hello'));
|
||||||
ByteData? envelope;
|
ByteData? envelope;
|
||||||
await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage('ch7', call, (ByteData? result) {
|
await TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.handlePlatformMessage('ch7', call, (ByteData? result) {
|
||||||
envelope = result;
|
envelope = result;
|
||||||
});
|
});
|
||||||
try {
|
try {
|
||||||
@ -249,24 +249,14 @@ void main() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
test('can check the handler', () {
|
test('can check the mock handler', () async {
|
||||||
Future<dynamic> handler(MethodCall call) => Future<dynamic>.value(null);
|
Future<dynamic> handler(MethodCall call) => Future<dynamic>.value(null);
|
||||||
|
|
||||||
const MethodChannel channel = MethodChannel('test_handler');
|
const MethodChannel channel = MethodChannel('test_handler');
|
||||||
expect(channel.checkMethodCallHandler(null), true);
|
expect(TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.checkMockMessageHandler(channel.name, null), true);
|
||||||
expect(channel.checkMethodCallHandler(handler), false);
|
expect(TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.checkMockMessageHandler(channel.name, handler), false);
|
||||||
channel.setMethodCallHandler(handler);
|
TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMethodCallHandler(channel, handler);
|
||||||
expect(channel.checkMethodCallHandler(handler), true);
|
expect(TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.checkMockMessageHandler(channel.name, handler), true);
|
||||||
});
|
|
||||||
|
|
||||||
test('can check the mock handler', () {
|
|
||||||
Future<dynamic> handler(MethodCall call) => Future<dynamic>.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);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -275,7 +265,7 @@ void main() {
|
|||||||
const MethodCodec jsonMethod = JSONMethodCodec();
|
const MethodCodec jsonMethod = JSONMethodCodec();
|
||||||
const EventChannel channel = EventChannel('ch', jsonMethod);
|
const EventChannel channel = EventChannel('ch', jsonMethod);
|
||||||
void emitEvent(ByteData? event) {
|
void emitEvent(ByteData? event) {
|
||||||
ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage(
|
TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.handlePlatformMessage(
|
||||||
'ch',
|
'ch',
|
||||||
event,
|
event,
|
||||||
(ByteData? reply) {},
|
(ByteData? reply) {},
|
||||||
@ -283,7 +273,7 @@ void main() {
|
|||||||
}
|
}
|
||||||
test('can receive event stream', () async {
|
test('can receive event stream', () async {
|
||||||
bool canceled = false;
|
bool canceled = false;
|
||||||
ServicesBinding.instance!.defaultBinaryMessenger.setMockMessageHandler(
|
TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMessageHandler(
|
||||||
'ch',
|
'ch',
|
||||||
(ByteData? message) async {
|
(ByteData? message) async {
|
||||||
final Map<dynamic, dynamic> methodCall = jsonMessage.decodeMessage(message) as Map<dynamic, dynamic>;
|
final Map<dynamic, dynamic> methodCall = jsonMessage.decodeMessage(message) as Map<dynamic, dynamic>;
|
||||||
@ -308,7 +298,7 @@ void main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('can receive error event', () async {
|
test('can receive error event', () async {
|
||||||
ServicesBinding.instance!.defaultBinaryMessenger.setMockMessageHandler(
|
TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMessageHandler(
|
||||||
'ch',
|
'ch',
|
||||||
(ByteData? message) async {
|
(ByteData? message) async {
|
||||||
final Map<dynamic, dynamic> methodCall = jsonMessage.decodeMessage(message) as Map<dynamic, dynamic>;
|
final Map<dynamic, dynamic> methodCall = jsonMessage.decodeMessage(message) as Map<dynamic, dynamic>;
|
||||||
|
@ -7,24 +7,23 @@ import 'package:flutter/services.dart';
|
|||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
test('Mock binary message handler control test', () async {
|
TestWidgetsFlutterBinding.ensureInitialized();
|
||||||
// Initialize all bindings because defaultBinaryMessenger.send() needs a window.
|
|
||||||
TestWidgetsFlutterBinding.ensureInitialized();
|
|
||||||
|
|
||||||
|
test('Mock binary message handler control test', () async {
|
||||||
final List<ByteData?> log = <ByteData>[];
|
final List<ByteData?> log = <ByteData>[];
|
||||||
|
|
||||||
ServicesBinding.instance!.defaultBinaryMessenger.setMockMessageHandler('test1', (ByteData? message) async {
|
TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMessageHandler('test1', (ByteData? message) async {
|
||||||
log.add(message);
|
log.add(message);
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
|
|
||||||
final ByteData message = ByteData(2)..setUint16(0, 0xABCD);
|
final ByteData message = ByteData(2)..setUint16(0, 0xABCD);
|
||||||
await ServicesBinding.instance!.defaultBinaryMessenger.send('test1', message);
|
await TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.send('test1', message);
|
||||||
expect(log, equals(<ByteData>[message]));
|
expect(log, equals(<ByteData>[message]));
|
||||||
log.clear();
|
log.clear();
|
||||||
|
|
||||||
ServicesBinding.instance!.defaultBinaryMessenger.setMockMessageHandler('test1', null);
|
TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMessageHandler('test1', null);
|
||||||
await ServicesBinding.instance!.defaultBinaryMessenger.send('test1', message);
|
await TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.send('test1', message);
|
||||||
expect(log, isEmpty);
|
expect(log, isEmpty);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
@ -30,6 +29,7 @@ void main() {
|
|||||||
RawKeyboard.instance.removeListener(handleKey);
|
RawKeyboard.instance.removeListener(handleKey);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('No character is produced for non-printables', (WidgetTester tester) async {
|
testWidgets('No character is produced for non-printables', (WidgetTester tester) async {
|
||||||
for (final String platform in <String>['linux', 'android', 'macos', 'fuchsia', 'windows', 'web']) {
|
for (final String platform in <String>['linux', 'android', 'macos', 'fuchsia', 'windows', 'web']) {
|
||||||
void handleKey(RawKeyEvent event) {
|
void handleKey(RawKeyEvent event) {
|
||||||
@ -40,6 +40,7 @@ void main() {
|
|||||||
RawKeyboard.instance.removeListener(handleKey);
|
RawKeyboard.instance.removeListener(handleKey);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('keysPressed is maintained', (WidgetTester tester) async {
|
testWidgets('keysPressed is maintained', (WidgetTester tester) async {
|
||||||
for (final String platform in <String>['linux', 'android', 'macos', 'fuchsia', 'windows', 'ios']) {
|
for (final String platform in <String>['linux', 'android', 'macos', 'fuchsia', 'windows', 'ios']) {
|
||||||
RawKeyboard.instance.clearKeysPressed();
|
RawKeyboard.instance.clearKeysPressed();
|
||||||
@ -209,7 +210,7 @@ void main() {
|
|||||||
// when this event is received, but it's not in keysPressed yet.
|
// when this event is received, but it's not in keysPressed yet.
|
||||||
data['modifiers'] |= RawKeyEventDataMacOs.modifierLeftShift | RawKeyEventDataMacOs.modifierShift;
|
data['modifiers'] |= RawKeyEventDataMacOs.modifierLeftShift | RawKeyEventDataMacOs.modifierShift;
|
||||||
// dispatch the modified data.
|
// dispatch the modified data.
|
||||||
await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage(
|
await TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.handlePlatformMessage(
|
||||||
SystemChannels.keyEvent.name,
|
SystemChannels.keyEvent.name,
|
||||||
SystemChannels.keyEvent.codec.encodeMessage(data),
|
SystemChannels.keyEvent.codec.encodeMessage(data),
|
||||||
(ByteData? data) {},
|
(ByteData? data) {},
|
||||||
@ -234,7 +235,7 @@ void main() {
|
|||||||
// when this event is received, but it's not in keysPressed yet.
|
// when this event is received, but it's not in keysPressed yet.
|
||||||
data['modifiers'] |= RawKeyEventDataMacOs.modifierLeftShift | RawKeyEventDataMacOs.modifierShift;
|
data['modifiers'] |= RawKeyEventDataMacOs.modifierLeftShift | RawKeyEventDataMacOs.modifierShift;
|
||||||
// dispatch the modified data.
|
// dispatch the modified data.
|
||||||
await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage(
|
await TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.handlePlatformMessage(
|
||||||
SystemChannels.keyEvent.name,
|
SystemChannels.keyEvent.name,
|
||||||
SystemChannels.keyEvent.codec.encodeMessage(data),
|
SystemChannels.keyEvent.codec.encodeMessage(data),
|
||||||
(ByteData? data) {},
|
(ByteData? data) {},
|
||||||
@ -259,7 +260,7 @@ void main() {
|
|||||||
// when this event is received, but it's not in keysPressed yet.
|
// when this event is received, but it's not in keysPressed yet.
|
||||||
data['modifiers'] |= RawKeyEventDataWindows.modifierLeftShift | RawKeyEventDataWindows.modifierShift;
|
data['modifiers'] |= RawKeyEventDataWindows.modifierLeftShift | RawKeyEventDataWindows.modifierShift;
|
||||||
// dispatch the modified data.
|
// dispatch the modified data.
|
||||||
await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage(
|
await TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.handlePlatformMessage(
|
||||||
SystemChannels.keyEvent.name,
|
SystemChannels.keyEvent.name,
|
||||||
SystemChannels.keyEvent.codec.encodeMessage(data),
|
SystemChannels.keyEvent.codec.encodeMessage(data),
|
||||||
(ByteData? data) {},
|
(ByteData? data) {},
|
||||||
@ -284,7 +285,7 @@ void main() {
|
|||||||
// when this event is received, but it's not in keysPressed yet.
|
// when this event is received, but it's not in keysPressed yet.
|
||||||
data['metaState'] |= RawKeyEventDataAndroid.modifierLeftShift | RawKeyEventDataAndroid.modifierShift;
|
data['metaState'] |= RawKeyEventDataAndroid.modifierLeftShift | RawKeyEventDataAndroid.modifierShift;
|
||||||
// dispatch the modified data.
|
// dispatch the modified data.
|
||||||
await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage(
|
await TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.handlePlatformMessage(
|
||||||
SystemChannels.keyEvent.name,
|
SystemChannels.keyEvent.name,
|
||||||
SystemChannels.keyEvent.codec.encodeMessage(data),
|
SystemChannels.keyEvent.codec.encodeMessage(data),
|
||||||
(ByteData? data) {},
|
(ByteData? data) {},
|
||||||
@ -309,7 +310,7 @@ void main() {
|
|||||||
// when this event is received, but it's not in keysPressed yet.
|
// when this event is received, but it's not in keysPressed yet.
|
||||||
data['modifiers'] |= RawKeyEventDataFuchsia.modifierLeftShift;
|
data['modifiers'] |= RawKeyEventDataFuchsia.modifierLeftShift;
|
||||||
// dispatch the modified data.
|
// dispatch the modified data.
|
||||||
await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage(
|
await TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.handlePlatformMessage(
|
||||||
SystemChannels.keyEvent.name,
|
SystemChannels.keyEvent.name,
|
||||||
SystemChannels.keyEvent.codec.encodeMessage(data),
|
SystemChannels.keyEvent.codec.encodeMessage(data),
|
||||||
(ByteData? data) {},
|
(ByteData? data) {},
|
||||||
@ -334,7 +335,7 @@ void main() {
|
|||||||
// when this event is received, but it's not in keysPressed yet.
|
// when this event is received, but it's not in keysPressed yet.
|
||||||
data['modifiers'] |= GLFWKeyHelper.modifierShift;
|
data['modifiers'] |= GLFWKeyHelper.modifierShift;
|
||||||
// dispatch the modified data.
|
// dispatch the modified data.
|
||||||
await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage(
|
await TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.handlePlatformMessage(
|
||||||
SystemChannels.keyEvent.name,
|
SystemChannels.keyEvent.name,
|
||||||
SystemChannels.keyEvent.codec.encodeMessage(data),
|
SystemChannels.keyEvent.codec.encodeMessage(data),
|
||||||
(ByteData? data) {},
|
(ByteData? data) {},
|
||||||
@ -364,7 +365,7 @@ void main() {
|
|||||||
isDown: true,
|
isDown: true,
|
||||||
)..['metaState'] |= RawKeyEventDataWeb.modifierShift;
|
)..['metaState'] |= RawKeyEventDataWeb.modifierShift;
|
||||||
// Dispatch the modified data.
|
// Dispatch the modified data.
|
||||||
await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage(
|
await TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.handlePlatformMessage(
|
||||||
SystemChannels.keyEvent.name,
|
SystemChannels.keyEvent.name,
|
||||||
SystemChannels.keyEvent.codec.encodeMessage(data),
|
SystemChannels.keyEvent.codec.encodeMessage(data),
|
||||||
(ByteData? data) {},
|
(ByteData? data) {},
|
||||||
@ -456,7 +457,7 @@ void main() {
|
|||||||
RawKeyEventDataAndroid.modifierControl |
|
RawKeyEventDataAndroid.modifierControl |
|
||||||
RawKeyEventDataAndroid.modifierMeta;
|
RawKeyEventDataAndroid.modifierMeta;
|
||||||
// dispatch the modified data.
|
// dispatch the modified data.
|
||||||
await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage(
|
await TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.handlePlatformMessage(
|
||||||
SystemChannels.keyEvent.name,
|
SystemChannels.keyEvent.name,
|
||||||
SystemChannels.keyEvent.codec.encodeMessage(data),
|
SystemChannels.keyEvent.codec.encodeMessage(data),
|
||||||
(ByteData? data) {},
|
(ByteData? data) {},
|
||||||
@ -494,7 +495,7 @@ void main() {
|
|||||||
RawKeyEventDataMacOs.modifierCommand |
|
RawKeyEventDataMacOs.modifierCommand |
|
||||||
RawKeyEventDataMacOs.modifierControl;
|
RawKeyEventDataMacOs.modifierControl;
|
||||||
// dispatch the modified data.
|
// dispatch the modified data.
|
||||||
await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage(
|
await TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.handlePlatformMessage(
|
||||||
SystemChannels.keyEvent.name,
|
SystemChannels.keyEvent.name,
|
||||||
SystemChannels.keyEvent.codec.encodeMessage(data),
|
SystemChannels.keyEvent.codec.encodeMessage(data),
|
||||||
(ByteData? data) {},
|
(ByteData? data) {},
|
||||||
@ -570,7 +571,7 @@ void main() {
|
|||||||
RawKeyEventDataWindows.modifierAlt |
|
RawKeyEventDataWindows.modifierAlt |
|
||||||
RawKeyEventDataWindows.modifierControl;
|
RawKeyEventDataWindows.modifierControl;
|
||||||
// dispatch the modified data.
|
// dispatch the modified data.
|
||||||
await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage(
|
await TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.handlePlatformMessage(
|
||||||
SystemChannels.keyEvent.name,
|
SystemChannels.keyEvent.name,
|
||||||
SystemChannels.keyEvent.codec.encodeMessage(data),
|
SystemChannels.keyEvent.codec.encodeMessage(data),
|
||||||
(ByteData? data) {},
|
(ByteData? data) {},
|
||||||
@ -607,7 +608,7 @@ void main() {
|
|||||||
GLFWKeyHelper.modifierControl |
|
GLFWKeyHelper.modifierControl |
|
||||||
GLFWKeyHelper.modifierMeta;
|
GLFWKeyHelper.modifierMeta;
|
||||||
// dispatch the modified data.
|
// dispatch the modified data.
|
||||||
await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage(
|
await TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.handlePlatformMessage(
|
||||||
SystemChannels.keyEvent.name,
|
SystemChannels.keyEvent.name,
|
||||||
SystemChannels.keyEvent.codec.encodeMessage(data),
|
SystemChannels.keyEvent.codec.encodeMessage(data),
|
||||||
(ByteData? data) {},
|
(ByteData? data) {},
|
||||||
@ -645,7 +646,7 @@ void main() {
|
|||||||
RawKeyEventDataWeb.modifierControl |
|
RawKeyEventDataWeb.modifierControl |
|
||||||
RawKeyEventDataWeb.modifierMeta;
|
RawKeyEventDataWeb.modifierMeta;
|
||||||
// dispatch the modified data.
|
// dispatch the modified data.
|
||||||
await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage(
|
await TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.handlePlatformMessage(
|
||||||
SystemChannels.keyEvent.name,
|
SystemChannels.keyEvent.name,
|
||||||
SystemChannels.keyEvent.codec.encodeMessage(data),
|
SystemChannels.keyEvent.codec.encodeMessage(data),
|
||||||
(ByteData? data) {},
|
(ByteData? data) {},
|
||||||
@ -665,12 +666,6 @@ void main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('RawKeyboard asserts if no keys are in keysPressed after receiving a key down event', (WidgetTester tester) async {
|
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<String, dynamic> keyEventMessage;
|
final Map<String, dynamic> keyEventMessage;
|
||||||
if (kIsWeb) {
|
if (kIsWeb) {
|
||||||
keyEventMessage = const <String, dynamic>{
|
keyEventMessage = const <String, dynamic>{
|
||||||
@ -692,19 +687,15 @@ void main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await ServicesBinding.instance!.defaultBinaryMessenger
|
await TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.handlePlatformMessage(
|
||||||
.handlePlatformMessage(
|
|
||||||
SystemChannels.keyEvent.name,
|
SystemChannels.keyEvent.name,
|
||||||
SystemChannels.keyEvent.codec.encodeMessage(keyEventMessage),
|
SystemChannels.keyEvent.codec.encodeMessage(keyEventMessage),
|
||||||
(ByteData? data) {},
|
(ByteData? data) { },
|
||||||
);
|
);
|
||||||
} finally {
|
fail('Expected an exception, but did not get one.');
|
||||||
FlutterError.onError = oldHandler;
|
} on AssertionError catch (error) {
|
||||||
|
expect(error.toString(), contains('Attempted to send a key down event when no keys are in keysPressed'));
|
||||||
}
|
}
|
||||||
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'));
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -757,6 +748,7 @@ void main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
test('modifier keys are recognized when combined', () {
|
test('modifier keys are recognized when combined', () {
|
||||||
for (final int modifier in modifierTests.keys) {
|
for (final int modifier in modifierTests.keys) {
|
||||||
if (modifier == RawKeyEventDataAndroid.modifierFunction) {
|
if (modifier == RawKeyEventDataAndroid.modifierFunction) {
|
||||||
@ -799,6 +791,7 @@ void main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Printable keyboard keys are correctly translated', () {
|
test('Printable keyboard keys are correctly translated', () {
|
||||||
final RawKeyEvent keyAEvent = RawKeyEvent.fromMessage(<String, dynamic>{
|
final RawKeyEvent keyAEvent = RawKeyEvent.fromMessage(<String, dynamic>{
|
||||||
'type': 'keydown',
|
'type': 'keydown',
|
||||||
@ -817,6 +810,7 @@ void main() {
|
|||||||
expect(data.logicalKey, equals(LogicalKeyboardKey.keyA));
|
expect(data.logicalKey, equals(LogicalKeyboardKey.keyA));
|
||||||
expect(data.keyLabel, equals('a'));
|
expect(data.keyLabel, equals('a'));
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Control keyboard keys are correctly translated', () {
|
test('Control keyboard keys are correctly translated', () {
|
||||||
final RawKeyEvent escapeKeyEvent = RawKeyEvent.fromMessage(const <String, dynamic>{
|
final RawKeyEvent escapeKeyEvent = RawKeyEvent.fromMessage(const <String, dynamic>{
|
||||||
'type': 'keydown',
|
'type': 'keydown',
|
||||||
@ -833,6 +827,7 @@ void main() {
|
|||||||
expect(data.logicalKey, equals(LogicalKeyboardKey.escape));
|
expect(data.logicalKey, equals(LogicalKeyboardKey.escape));
|
||||||
expect(data.keyLabel, isEmpty);
|
expect(data.keyLabel, isEmpty);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Modifier keyboard keys are correctly translated', () {
|
test('Modifier keyboard keys are correctly translated', () {
|
||||||
final RawKeyEvent shiftLeftKeyEvent = RawKeyEvent.fromMessage(const <String, dynamic>{
|
final RawKeyEvent shiftLeftKeyEvent = RawKeyEvent.fromMessage(const <String, dynamic>{
|
||||||
'type': 'keydown',
|
'type': 'keydown',
|
||||||
@ -850,6 +845,7 @@ void main() {
|
|||||||
expect(data.logicalKey, equals(LogicalKeyboardKey.shiftLeft));
|
expect(data.logicalKey, equals(LogicalKeyboardKey.shiftLeft));
|
||||||
expect(data.keyLabel, isEmpty);
|
expect(data.keyLabel, isEmpty);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('DPAD keys from a joystick give physical key mappings', () {
|
test('DPAD keys from a joystick give physical key mappings', () {
|
||||||
final RawKeyEvent joystickDpadDown = RawKeyEvent.fromMessage(const <String, dynamic>{
|
final RawKeyEvent joystickDpadDown = RawKeyEvent.fromMessage(const <String, dynamic>{
|
||||||
'type': 'keydown',
|
'type': 'keydown',
|
||||||
@ -867,6 +863,7 @@ void main() {
|
|||||||
expect(data.logicalKey, equals(LogicalKeyboardKey.arrowDown));
|
expect(data.logicalKey, equals(LogicalKeyboardKey.arrowDown));
|
||||||
expect(data.keyLabel, isEmpty);
|
expect(data.keyLabel, isEmpty);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Arrow keys from a keyboard give correct physical key mappings', () {
|
test('Arrow keys from a keyboard give correct physical key mappings', () {
|
||||||
final RawKeyEvent joystickDpadDown = RawKeyEvent.fromMessage(const <String, dynamic>{
|
final RawKeyEvent joystickDpadDown = RawKeyEvent.fromMessage(const <String, dynamic>{
|
||||||
'type': 'keydown',
|
'type': 'keydown',
|
||||||
@ -883,6 +880,7 @@ void main() {
|
|||||||
expect(data.logicalKey, equals(LogicalKeyboardKey.arrowDown));
|
expect(data.logicalKey, equals(LogicalKeyboardKey.arrowDown));
|
||||||
expect(data.keyLabel, isEmpty);
|
expect(data.keyLabel, isEmpty);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('DPAD center from a game pad gives physical key mappings', () {
|
test('DPAD center from a game pad gives physical key mappings', () {
|
||||||
final RawKeyEvent joystickDpadCenter = RawKeyEvent.fromMessage(const <String, dynamic>{
|
final RawKeyEvent joystickDpadCenter = RawKeyEvent.fromMessage(const <String, dynamic>{
|
||||||
'type': 'keydown',
|
'type': 'keydown',
|
||||||
@ -900,6 +898,7 @@ void main() {
|
|||||||
expect(data.logicalKey, equals(LogicalKeyboardKey.select));
|
expect(data.logicalKey, equals(LogicalKeyboardKey.select));
|
||||||
expect(data.keyLabel, isEmpty);
|
expect(data.keyLabel, isEmpty);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Device id is read from message', () {
|
test('Device id is read from message', () {
|
||||||
final RawKeyEvent joystickDpadCenter = RawKeyEvent.fromMessage(const <String, dynamic>{
|
final RawKeyEvent joystickDpadCenter = RawKeyEvent.fromMessage(const <String, dynamic>{
|
||||||
'type': 'keydown',
|
'type': 'keydown',
|
||||||
@ -915,6 +914,7 @@ void main() {
|
|||||||
final RawKeyEventDataAndroid data = joystickDpadCenter.data as RawKeyEventDataAndroid;
|
final RawKeyEventDataAndroid data = joystickDpadCenter.data as RawKeyEventDataAndroid;
|
||||||
expect(data.deviceId, equals(10));
|
expect(data.deviceId, equals(10));
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Repeat count is passed correctly', () {
|
test('Repeat count is passed correctly', () {
|
||||||
final RawKeyEvent repeatCountEvent = RawKeyEvent.fromMessage(<String, dynamic>{
|
final RawKeyEvent repeatCountEvent = RawKeyEvent.fromMessage(<String, dynamic>{
|
||||||
'type': 'keydown',
|
'type': 'keydown',
|
||||||
@ -931,6 +931,7 @@ void main() {
|
|||||||
final RawKeyEventDataAndroid data = repeatCountEvent.data as RawKeyEventDataAndroid;
|
final RawKeyEventDataAndroid data = repeatCountEvent.data as RawKeyEventDataAndroid;
|
||||||
expect(data.repeatCount, equals(42));
|
expect(data.repeatCount, equals(42));
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('Key events are responded to correctly.', (WidgetTester tester) async {
|
testWidgets('Key events are responded to correctly.', (WidgetTester tester) async {
|
||||||
expect(RawKeyboard.instance.keysPressed, isEmpty);
|
expect(RawKeyboard.instance.keysPressed, isEmpty);
|
||||||
// Generate the data for a regular key down event.
|
// Generate the data for a regular key down event.
|
||||||
@ -940,7 +941,7 @@ void main() {
|
|||||||
isDown: true,
|
isDown: true,
|
||||||
);
|
);
|
||||||
Map<String, dynamic>? message;
|
Map<String, dynamic>? message;
|
||||||
await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage(
|
await TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.handlePlatformMessage(
|
||||||
SystemChannels.keyEvent.name,
|
SystemChannels.keyEvent.name,
|
||||||
SystemChannels.keyEvent.codec.encodeMessage(data),
|
SystemChannels.keyEvent.codec.encodeMessage(data),
|
||||||
(ByteData? data) {
|
(ByteData? data) {
|
||||||
@ -963,7 +964,7 @@ void main() {
|
|||||||
focusNode.requestFocus();
|
focusNode.requestFocus();
|
||||||
await tester.pump();
|
await tester.pump();
|
||||||
|
|
||||||
await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage(
|
await TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.handlePlatformMessage(
|
||||||
SystemChannels.keyEvent.name,
|
SystemChannels.keyEvent.name,
|
||||||
SystemChannels.keyEvent.codec.encodeMessage(data),
|
SystemChannels.keyEvent.codec.encodeMessage(data),
|
||||||
(ByteData? data) {
|
(ByteData? data) {
|
||||||
@ -971,7 +972,7 @@ void main() {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
expect(message, equals(<String, dynamic>{ 'handled': true }));
|
expect(message, equals(<String, dynamic>{ 'handled': true }));
|
||||||
ServicesBinding.instance!.defaultBinaryMessenger.setMockMessageHandler(SystemChannels.keyEvent.name, null);
|
tester.binding.defaultBinaryMessenger.setMockMessageHandler(SystemChannels.keyEvent.name, null);
|
||||||
});
|
});
|
||||||
}, skip: isBrowser); // This is an Android-specific group.
|
}, skip: isBrowser); // This is an Android-specific group.
|
||||||
|
|
||||||
@ -1019,6 +1020,7 @@ void main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
test('modifier keys are recognized when combined', () {
|
test('modifier keys are recognized when combined', () {
|
||||||
for (final int modifier in modifierTests.keys) {
|
for (final int modifier in modifierTests.keys) {
|
||||||
if (modifier == RawKeyEventDataFuchsia.modifierCapsLock) {
|
if (modifier == RawKeyEventDataFuchsia.modifierCapsLock) {
|
||||||
@ -1052,6 +1054,7 @@ void main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Printable keyboard keys are correctly translated', () {
|
test('Printable keyboard keys are correctly translated', () {
|
||||||
final RawKeyEvent keyAEvent = RawKeyEvent.fromMessage(<String, dynamic>{
|
final RawKeyEvent keyAEvent = RawKeyEvent.fromMessage(<String, dynamic>{
|
||||||
'type': 'keydown',
|
'type': 'keydown',
|
||||||
@ -1065,6 +1068,7 @@ void main() {
|
|||||||
expect(data.logicalKey, equals(LogicalKeyboardKey.keyA));
|
expect(data.logicalKey, equals(LogicalKeyboardKey.keyA));
|
||||||
expect(data.keyLabel, equals('a'));
|
expect(data.keyLabel, equals('a'));
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Control keyboard keys are correctly translated', () {
|
test('Control keyboard keys are correctly translated', () {
|
||||||
final RawKeyEvent escapeKeyEvent = RawKeyEvent.fromMessage(const <String, dynamic>{
|
final RawKeyEvent escapeKeyEvent = RawKeyEvent.fromMessage(const <String, dynamic>{
|
||||||
'type': 'keydown',
|
'type': 'keydown',
|
||||||
@ -1136,6 +1140,7 @@ void main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
test('modifier keys are recognized when combined', () {
|
test('modifier keys are recognized when combined', () {
|
||||||
for (final int modifier in modifierTests.keys) {
|
for (final int modifier in modifierTests.keys) {
|
||||||
if (modifier == RawKeyEventDataMacOs.modifierCapsLock) {
|
if (modifier == RawKeyEventDataMacOs.modifierCapsLock) {
|
||||||
@ -1175,6 +1180,7 @@ void main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Printable keyboard keys are correctly translated', () {
|
test('Printable keyboard keys are correctly translated', () {
|
||||||
const String unmodifiedCharacter = 'a';
|
const String unmodifiedCharacter = 'a';
|
||||||
final RawKeyEvent keyAEvent = RawKeyEvent.fromMessage(const <String, dynamic>{
|
final RawKeyEvent keyAEvent = RawKeyEvent.fromMessage(const <String, dynamic>{
|
||||||
@ -1190,6 +1196,7 @@ void main() {
|
|||||||
expect(data.logicalKey, equals(LogicalKeyboardKey.keyA));
|
expect(data.logicalKey, equals(LogicalKeyboardKey.keyA));
|
||||||
expect(data.keyLabel, equals('a'));
|
expect(data.keyLabel, equals('a'));
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Control keyboard keys are correctly translated', () {
|
test('Control keyboard keys are correctly translated', () {
|
||||||
final RawKeyEvent escapeKeyEvent = RawKeyEvent.fromMessage(const <String, dynamic>{
|
final RawKeyEvent escapeKeyEvent = RawKeyEvent.fromMessage(const <String, dynamic>{
|
||||||
'type': 'keydown',
|
'type': 'keydown',
|
||||||
@ -1281,6 +1288,7 @@ void main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
test('modifier keys are recognized when combined', () {
|
test('modifier keys are recognized when combined', () {
|
||||||
for (final int modifier in modifierTests.keys) {
|
for (final int modifier in modifierTests.keys) {
|
||||||
if (modifier == RawKeyEventDataIos.modifierCapsLock) {
|
if (modifier == RawKeyEventDataIos.modifierCapsLock) {
|
||||||
@ -1320,6 +1328,7 @@ void main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Printable keyboard keys are correctly translated', () {
|
test('Printable keyboard keys are correctly translated', () {
|
||||||
const String unmodifiedCharacter = 'a';
|
const String unmodifiedCharacter = 'a';
|
||||||
final RawKeyEvent keyAEvent = RawKeyEvent.fromMessage(const <String, dynamic>{
|
final RawKeyEvent keyAEvent = RawKeyEvent.fromMessage(const <String, dynamic>{
|
||||||
@ -1335,6 +1344,7 @@ void main() {
|
|||||||
expect(data.logicalKey, equals(LogicalKeyboardKey.keyA));
|
expect(data.logicalKey, equals(LogicalKeyboardKey.keyA));
|
||||||
expect(data.keyLabel, equals('a'));
|
expect(data.keyLabel, equals('a'));
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Control keyboard keys are correctly translated', () {
|
test('Control keyboard keys are correctly translated', () {
|
||||||
final RawKeyEvent escapeKeyEvent = RawKeyEvent.fromMessage(const <String, dynamic>{
|
final RawKeyEvent escapeKeyEvent = RawKeyEvent.fromMessage(const <String, dynamic>{
|
||||||
'type': 'keydown',
|
'type': 'keydown',
|
||||||
@ -1427,6 +1437,7 @@ void main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
test('modifier keys are recognized when combined', () {
|
test('modifier keys are recognized when combined', () {
|
||||||
for (final int modifier in modifierTests.keys) {
|
for (final int modifier in modifierTests.keys) {
|
||||||
if (modifier == RawKeyEventDataWindows.modifierCaps) {
|
if (modifier == RawKeyEventDataWindows.modifierCaps) {
|
||||||
@ -1466,6 +1477,7 @@ void main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Printable keyboard keys are correctly translated', () {
|
test('Printable keyboard keys are correctly translated', () {
|
||||||
const int unmodifiedCharacter = 97; // ASCII value for 'a'.
|
const int unmodifiedCharacter = 97; // ASCII value for 'a'.
|
||||||
final RawKeyEvent keyAEvent = RawKeyEvent.fromMessage(const <String, dynamic>{
|
final RawKeyEvent keyAEvent = RawKeyEvent.fromMessage(const <String, dynamic>{
|
||||||
@ -1481,6 +1493,7 @@ void main() {
|
|||||||
expect(data.logicalKey, equals(LogicalKeyboardKey.keyA));
|
expect(data.logicalKey, equals(LogicalKeyboardKey.keyA));
|
||||||
expect(data.keyLabel, equals('a'));
|
expect(data.keyLabel, equals('a'));
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Control keyboard keys are correctly translated', () {
|
test('Control keyboard keys are correctly translated', () {
|
||||||
final RawKeyEvent escapeKeyEvent = RawKeyEvent.fromMessage(const <String, dynamic>{
|
final RawKeyEvent escapeKeyEvent = RawKeyEvent.fromMessage(const <String, dynamic>{
|
||||||
'type': 'keydown',
|
'type': 'keydown',
|
||||||
@ -1495,6 +1508,7 @@ void main() {
|
|||||||
expect(data.logicalKey, equals(LogicalKeyboardKey.escape));
|
expect(data.logicalKey, equals(LogicalKeyboardKey.escape));
|
||||||
expect(data.keyLabel, isEmpty);
|
expect(data.keyLabel, isEmpty);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Modifier keyboard keys are correctly translated', () {
|
test('Modifier keyboard keys are correctly translated', () {
|
||||||
final RawKeyEvent shiftLeftKeyEvent = RawKeyEvent.fromMessage(const <String, dynamic>{
|
final RawKeyEvent shiftLeftKeyEvent = RawKeyEvent.fromMessage(const <String, dynamic>{
|
||||||
'type': 'keydown',
|
'type': 'keydown',
|
||||||
@ -1509,6 +1523,7 @@ void main() {
|
|||||||
expect(data.logicalKey, equals(LogicalKeyboardKey.shiftLeft));
|
expect(data.logicalKey, equals(LogicalKeyboardKey.shiftLeft));
|
||||||
expect(data.keyLabel, isEmpty);
|
expect(data.keyLabel, isEmpty);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Unprintable keyboard keys are correctly translated', () {
|
test('Unprintable keyboard keys are correctly translated', () {
|
||||||
final RawKeyEvent leftArrowKey = RawKeyEvent.fromMessage(const <String, dynamic>{
|
final RawKeyEvent leftArrowKey = RawKeyEvent.fromMessage(const <String, dynamic>{
|
||||||
'type': 'keydown',
|
'type': 'keydown',
|
||||||
@ -1522,6 +1537,7 @@ void main() {
|
|||||||
expect(data.physicalKey, equals(PhysicalKeyboardKey.arrowLeft));
|
expect(data.physicalKey, equals(PhysicalKeyboardKey.arrowLeft));
|
||||||
expect(data.logicalKey, equals(LogicalKeyboardKey.arrowLeft));
|
expect(data.logicalKey, equals(LogicalKeyboardKey.arrowLeft));
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('Win32 VK_PROCESSKEY events are skipped', (WidgetTester tester) async {
|
testWidgets('Win32 VK_PROCESSKEY events are skipped', (WidgetTester tester) async {
|
||||||
const String platform = 'windows';
|
const String platform = 'windows';
|
||||||
bool lastHandled = true;
|
bool lastHandled = true;
|
||||||
@ -1620,6 +1636,7 @@ void main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
test('modifier keys are recognized when combined', () {
|
test('modifier keys are recognized when combined', () {
|
||||||
for (final int modifier in modifierTests.keys) {
|
for (final int modifier in modifierTests.keys) {
|
||||||
if (modifier == GLFWKeyHelper.modifierControl) {
|
if (modifier == GLFWKeyHelper.modifierControl) {
|
||||||
@ -1660,6 +1677,7 @@ void main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Printable keyboard keys are correctly translated', () {
|
test('Printable keyboard keys are correctly translated', () {
|
||||||
final RawKeyEvent keyAEvent = RawKeyEvent.fromMessage(const <String, dynamic>{
|
final RawKeyEvent keyAEvent = RawKeyEvent.fromMessage(const <String, dynamic>{
|
||||||
'type': 'keydown',
|
'type': 'keydown',
|
||||||
@ -1675,6 +1693,7 @@ void main() {
|
|||||||
expect(data.logicalKey, equals(LogicalKeyboardKey.keyQ));
|
expect(data.logicalKey, equals(LogicalKeyboardKey.keyQ));
|
||||||
expect(data.keyLabel, equals('q'));
|
expect(data.keyLabel, equals('q'));
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Code points with two Unicode scalar values are allowed', () {
|
test('Code points with two Unicode scalar values are allowed', () {
|
||||||
final RawKeyEvent keyAEvent = RawKeyEvent.fromMessage(const <String, dynamic>{
|
final RawKeyEvent keyAEvent = RawKeyEvent.fromMessage(const <String, dynamic>{
|
||||||
'type': 'keydown',
|
'type': 'keydown',
|
||||||
@ -1723,6 +1742,7 @@ void main() {
|
|||||||
expect(data.logicalKey, equals(LogicalKeyboardKey.escape));
|
expect(data.logicalKey, equals(LogicalKeyboardKey.escape));
|
||||||
expect(data.keyLabel, isEmpty);
|
expect(data.keyLabel, isEmpty);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Modifier keyboard keys are correctly translated', () {
|
test('Modifier keyboard keys are correctly translated', () {
|
||||||
final RawKeyEvent shiftLeftKeyEvent = RawKeyEvent.fromMessage(const <String, dynamic>{
|
final RawKeyEvent shiftLeftKeyEvent = RawKeyEvent.fromMessage(const <String, dynamic>{
|
||||||
'type': 'keydown',
|
'type': 'keydown',
|
||||||
@ -1804,6 +1824,7 @@ void main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
test('modifier keys are recognized when combined', () {
|
test('modifier keys are recognized when combined', () {
|
||||||
for (final int modifier in modifierTests.keys) {
|
for (final int modifier in modifierTests.keys) {
|
||||||
if (modifier == GtkKeyHelper.modifierControl) {
|
if (modifier == GtkKeyHelper.modifierControl) {
|
||||||
@ -1844,6 +1865,7 @@ void main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Printable keyboard keys are correctly translated', () {
|
test('Printable keyboard keys are correctly translated', () {
|
||||||
final RawKeyEvent keyAEvent = RawKeyEvent.fromMessage(const <String, dynamic>{
|
final RawKeyEvent keyAEvent = RawKeyEvent.fromMessage(const <String, dynamic>{
|
||||||
'type': 'keydown',
|
'type': 'keydown',
|
||||||
@ -1859,6 +1881,7 @@ void main() {
|
|||||||
expect(data.logicalKey, equals(LogicalKeyboardKey.keyQ));
|
expect(data.logicalKey, equals(LogicalKeyboardKey.keyQ));
|
||||||
expect(data.keyLabel, equals('q'));
|
expect(data.keyLabel, equals('q'));
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Code points with two Unicode scalar values are allowed', () {
|
test('Code points with two Unicode scalar values are allowed', () {
|
||||||
final RawKeyEvent keyAEvent = RawKeyEvent.fromMessage(const <String, dynamic>{
|
final RawKeyEvent keyAEvent = RawKeyEvent.fromMessage(const <String, dynamic>{
|
||||||
'type': 'keydown',
|
'type': 'keydown',
|
||||||
@ -1907,6 +1930,7 @@ void main() {
|
|||||||
expect(data.logicalKey, equals(LogicalKeyboardKey.escape));
|
expect(data.logicalKey, equals(LogicalKeyboardKey.escape));
|
||||||
expect(data.keyLabel, isEmpty);
|
expect(data.keyLabel, isEmpty);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Modifier keyboard keys are correctly translated', () {
|
test('Modifier keyboard keys are correctly translated', () {
|
||||||
final RawKeyEvent shiftLeftKeyEvent = RawKeyEvent.fromMessage(const <String, dynamic>{
|
final RawKeyEvent shiftLeftKeyEvent = RawKeyEvent.fromMessage(const <String, dynamic>{
|
||||||
'type': 'keydown',
|
'type': 'keydown',
|
||||||
@ -1960,6 +1984,7 @@ void main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
test('modifier keys are recognized when combined', () {
|
test('modifier keys are recognized when combined', () {
|
||||||
for (final int modifier in modifierTests.keys) {
|
for (final int modifier in modifierTests.keys) {
|
||||||
if (modifier == RawKeyEventDataWeb.modifierMeta) {
|
if (modifier == RawKeyEventDataWeb.modifierMeta) {
|
||||||
@ -1992,6 +2017,7 @@ void main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Printable keyboard keys are correctly translated', () {
|
test('Printable keyboard keys are correctly translated', () {
|
||||||
final RawKeyEvent keyAEvent = RawKeyEvent.fromMessage(const <String, dynamic>{
|
final RawKeyEvent keyAEvent = RawKeyEvent.fromMessage(const <String, dynamic>{
|
||||||
'type': 'keydown',
|
'type': 'keydown',
|
||||||
@ -2005,6 +2031,7 @@ void main() {
|
|||||||
expect(data.logicalKey, equals(LogicalKeyboardKey.keyA));
|
expect(data.logicalKey, equals(LogicalKeyboardKey.keyA));
|
||||||
expect(data.keyLabel, equals('a'));
|
expect(data.keyLabel, equals('a'));
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Control keyboard keys are correctly translated', () {
|
test('Control keyboard keys are correctly translated', () {
|
||||||
final RawKeyEvent escapeKeyEvent = RawKeyEvent.fromMessage(const <String, dynamic>{
|
final RawKeyEvent escapeKeyEvent = RawKeyEvent.fromMessage(const <String, dynamic>{
|
||||||
'type': 'keydown',
|
'type': 'keydown',
|
||||||
@ -2017,6 +2044,7 @@ void main() {
|
|||||||
expect(data.logicalKey, equals(LogicalKeyboardKey.escape));
|
expect(data.logicalKey, equals(LogicalKeyboardKey.escape));
|
||||||
expect(data.keyLabel, isEmpty);
|
expect(data.keyLabel, isEmpty);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Modifier keyboard keys are correctly translated', () {
|
test('Modifier keyboard keys are correctly translated', () {
|
||||||
final RawKeyEvent shiftKeyEvent = RawKeyEvent.fromMessage(const <String, dynamic>{
|
final RawKeyEvent shiftKeyEvent = RawKeyEvent.fromMessage(const <String, dynamic>{
|
||||||
'type': 'keydown',
|
'type': 'keydown',
|
||||||
@ -2029,6 +2057,7 @@ void main() {
|
|||||||
expect(data.logicalKey, equals(LogicalKeyboardKey.shiftLeft));
|
expect(data.logicalKey, equals(LogicalKeyboardKey.shiftLeft));
|
||||||
expect(data.keyLabel, isEmpty);
|
expect(data.keyLabel, isEmpty);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Arrow keys from a keyboard give correct physical key mappings', () {
|
test('Arrow keys from a keyboard give correct physical key mappings', () {
|
||||||
final RawKeyEvent arrowKeyDown = RawKeyEvent.fromMessage(const <String, dynamic>{
|
final RawKeyEvent arrowKeyDown = RawKeyEvent.fromMessage(const <String, dynamic>{
|
||||||
'type': 'keydown',
|
'type': 'keydown',
|
||||||
|
@ -18,7 +18,7 @@ void main() {
|
|||||||
testWidgets('root bucket retrieval', (WidgetTester tester) async {
|
testWidgets('root bucket retrieval', (WidgetTester tester) async {
|
||||||
final List<MethodCall> callsToEngine = <MethodCall>[];
|
final List<MethodCall> callsToEngine = <MethodCall>[];
|
||||||
final Completer<Map<dynamic, dynamic>> result = Completer<Map<dynamic, dynamic>>();
|
final Completer<Map<dynamic, dynamic>> result = Completer<Map<dynamic, dynamic>>();
|
||||||
SystemChannels.restoration.setMockMethodCallHandler((MethodCall call) {
|
tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.restoration, (MethodCall call) {
|
||||||
callsToEngine.add(call);
|
callsToEngine.add(call);
|
||||||
return result.future;
|
return result.future;
|
||||||
});
|
});
|
||||||
@ -64,7 +64,7 @@ void main() {
|
|||||||
testWidgets('root bucket received from engine before retrieval', (WidgetTester tester) async {
|
testWidgets('root bucket received from engine before retrieval', (WidgetTester tester) async {
|
||||||
SystemChannels.restoration.setMethodCallHandler(null);
|
SystemChannels.restoration.setMethodCallHandler(null);
|
||||||
final List<MethodCall> callsToEngine = <MethodCall>[];
|
final List<MethodCall> callsToEngine = <MethodCall>[];
|
||||||
SystemChannels.restoration.setMockMethodCallHandler((MethodCall call) async {
|
tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.restoration, (MethodCall call) async {
|
||||||
callsToEngine.add(call);
|
callsToEngine.add(call);
|
||||||
});
|
});
|
||||||
final RestorationManager manager = RestorationManager();
|
final RestorationManager manager = RestorationManager();
|
||||||
@ -83,7 +83,7 @@ void main() {
|
|||||||
SystemChannels.restoration.setMethodCallHandler(null);
|
SystemChannels.restoration.setMethodCallHandler(null);
|
||||||
final List<MethodCall> callsToEngine = <MethodCall>[];
|
final List<MethodCall> callsToEngine = <MethodCall>[];
|
||||||
final Completer<Map<dynamic, dynamic>> result = Completer<Map<dynamic, dynamic>>();
|
final Completer<Map<dynamic, dynamic>> result = Completer<Map<dynamic, dynamic>>();
|
||||||
SystemChannels.restoration.setMockMethodCallHandler((MethodCall call) {
|
tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.restoration, (MethodCall call) {
|
||||||
callsToEngine.add(call);
|
callsToEngine.add(call);
|
||||||
return result.future;
|
return result.future;
|
||||||
});
|
});
|
||||||
@ -110,7 +110,7 @@ void main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('root bucket is properly replaced when new data is available', (WidgetTester tester) async {
|
testWidgets('root bucket is properly replaced when new data is available', (WidgetTester tester) async {
|
||||||
SystemChannels.restoration.setMockMethodCallHandler((MethodCall call) async {
|
tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.restoration, (MethodCall call) async {
|
||||||
return _createEncodedRestorationData1();
|
return _createEncodedRestorationData1();
|
||||||
});
|
});
|
||||||
final RestorationManager manager = RestorationManager();
|
final RestorationManager manager = RestorationManager();
|
||||||
@ -152,7 +152,7 @@ void main() {
|
|||||||
testWidgets('returns null as root bucket when restoration is disabled', (WidgetTester tester) async {
|
testWidgets('returns null as root bucket when restoration is disabled', (WidgetTester tester) async {
|
||||||
final List<MethodCall> callsToEngine = <MethodCall>[];
|
final List<MethodCall> callsToEngine = <MethodCall>[];
|
||||||
final Completer<Map<dynamic, dynamic>> result = Completer<Map<dynamic, dynamic>>();
|
final Completer<Map<dynamic, dynamic>> result = Completer<Map<dynamic, dynamic>>();
|
||||||
SystemChannels.restoration.setMockMethodCallHandler((MethodCall call) {
|
tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.restoration, (MethodCall call) {
|
||||||
callsToEngine.add(call);
|
callsToEngine.add(call);
|
||||||
return result.future;
|
return result.future;
|
||||||
});
|
});
|
||||||
@ -195,7 +195,7 @@ void main() {
|
|||||||
testWidgets('flushData', (WidgetTester tester) async {
|
testWidgets('flushData', (WidgetTester tester) async {
|
||||||
final List<MethodCall> callsToEngine = <MethodCall>[];
|
final List<MethodCall> callsToEngine = <MethodCall>[];
|
||||||
final Completer<Map<dynamic, dynamic>> result = Completer<Map<dynamic, dynamic>>();
|
final Completer<Map<dynamic, dynamic>> result = Completer<Map<dynamic, dynamic>>();
|
||||||
SystemChannels.restoration.setMockMethodCallHandler((MethodCall call) {
|
tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.restoration, (MethodCall call) {
|
||||||
callsToEngine.add(call);
|
callsToEngine.add(call);
|
||||||
return result.future;
|
return result.future;
|
||||||
});
|
});
|
||||||
@ -230,7 +230,7 @@ void main() {
|
|||||||
|
|
||||||
testWidgets('isReplacing', (WidgetTester tester) async {
|
testWidgets('isReplacing', (WidgetTester tester) async {
|
||||||
final Completer<Map<dynamic, dynamic>> result = Completer<Map<dynamic, dynamic>>();
|
final Completer<Map<dynamic, dynamic>> result = Completer<Map<dynamic, dynamic>>();
|
||||||
SystemChannels.restoration.setMockMethodCallHandler((MethodCall call) {
|
tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.restoration, (MethodCall call) {
|
||||||
return result.future;
|
return result.future;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -7,6 +7,8 @@ import 'package:flutter/services.dart';
|
|||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
TestWidgetsFlutterBinding.ensureInitialized();
|
||||||
|
|
||||||
testWidgets('SystemChrome overlay style test', (WidgetTester tester) async {
|
testWidgets('SystemChrome overlay style test', (WidgetTester tester) async {
|
||||||
// The first call is a cache miss and will queue a microtask
|
// The first call is a cache miss and will queue a microtask
|
||||||
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle.light);
|
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle.light);
|
||||||
@ -24,7 +26,7 @@ void main() {
|
|||||||
test('setPreferredOrientations control test', () async {
|
test('setPreferredOrientations control test', () async {
|
||||||
final List<MethodCall> log = <MethodCall>[];
|
final List<MethodCall> log = <MethodCall>[];
|
||||||
|
|
||||||
SystemChannels.platform.setMockMethodCallHandler((MethodCall methodCall) async {
|
TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async {
|
||||||
log.add(methodCall);
|
log.add(methodCall);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -42,7 +44,7 @@ void main() {
|
|||||||
test('setApplicationSwitcherDescription control test', () async {
|
test('setApplicationSwitcherDescription control test', () async {
|
||||||
final List<MethodCall> log = <MethodCall>[];
|
final List<MethodCall> log = <MethodCall>[];
|
||||||
|
|
||||||
SystemChannels.platform.setMockMethodCallHandler((MethodCall methodCall) async {
|
TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async {
|
||||||
log.add(methodCall);
|
log.add(methodCall);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -60,7 +62,7 @@ void main() {
|
|||||||
test('setApplicationSwitcherDescription missing plugin', () async {
|
test('setApplicationSwitcherDescription missing plugin', () async {
|
||||||
final List<ByteData?> log = <ByteData>[];
|
final List<ByteData?> log = <ByteData>[];
|
||||||
|
|
||||||
ServicesBinding.instance!.defaultBinaryMessenger.setMockMessageHandler('flutter/platform', (ByteData? message) async {
|
TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMessageHandler('flutter/platform', (ByteData? message) async {
|
||||||
log.add(message);
|
log.add(message);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -74,7 +76,7 @@ void main() {
|
|||||||
test('setEnabledSystemUIOverlays control test', () async {
|
test('setEnabledSystemUIOverlays control test', () async {
|
||||||
final List<MethodCall> log = <MethodCall>[];
|
final List<MethodCall> log = <MethodCall>[];
|
||||||
|
|
||||||
SystemChannels.platform.setMockMethodCallHandler((MethodCall methodCall) async {
|
TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async {
|
||||||
log.add(methodCall);
|
log.add(methodCall);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ void main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
test('System navigator control test - platform messages', () async {
|
test('System navigator control test - platform messages', () async {
|
||||||
SystemChannels.platform.setMockMethodCallHandler((MethodCall methodCall) async {
|
TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async {
|
||||||
log.add(methodCall);
|
log.add(methodCall);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -26,11 +26,11 @@ void main() {
|
|||||||
isMethodCall('SystemNavigator.pop', arguments: null),
|
isMethodCall('SystemNavigator.pop', arguments: null),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
SystemChannels.platform.setMockMethodCallHandler(null);
|
TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, null);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('System navigator control test - navigation messages', () async {
|
test('System navigator control test - navigation messages', () async {
|
||||||
SystemChannels.navigation.setMockMethodCallHandler((MethodCall methodCall) async {
|
TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.navigation, (MethodCall methodCall) async {
|
||||||
log.add(methodCall);
|
log.add(methodCall);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -54,6 +54,6 @@ void main() {
|
|||||||
isMethodCall('routeUpdated', arguments: <String, dynamic>{ 'routeName': 'a', 'previousRouteName': 'b' }),
|
isMethodCall('routeUpdated', arguments: <String, dynamic>{ 'routeName': 'a', 'previousRouteName': 'b' }),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
SystemChannels.navigation.setMockMethodCallHandler(null);
|
TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.navigation, null);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ void main() {
|
|||||||
test('System sound control test', () async {
|
test('System sound control test', () async {
|
||||||
final List<MethodCall> log = <MethodCall>[];
|
final List<MethodCall> log = <MethodCall>[];
|
||||||
|
|
||||||
SystemChannels.platform.setMockMethodCallHandler((MethodCall methodCall) async {
|
TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async {
|
||||||
log.add(methodCall);
|
log.add(methodCall);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -466,16 +466,6 @@ class FakeTextChannel implements MethodChannel {
|
|||||||
@override
|
@override
|
||||||
void setMethodCallHandler(Future<void> Function(MethodCall call)? handler) => incoming = handler;
|
void setMethodCallHandler(Future<void> Function(MethodCall call)? handler) => incoming = handler;
|
||||||
|
|
||||||
@override
|
|
||||||
bool checkMethodCallHandler(Future<void> Function(MethodCall call)? handler) => throw UnimplementedError();
|
|
||||||
|
|
||||||
|
|
||||||
@override
|
|
||||||
void setMockMethodCallHandler(Future<void>? Function(MethodCall call)? handler) => throw UnimplementedError();
|
|
||||||
|
|
||||||
@override
|
|
||||||
bool checkMockMethodCallHandler(Future<void> Function(MethodCall call)? handler) => throw UnimplementedError();
|
|
||||||
|
|
||||||
void validateOutgoingMethodCalls(List<MethodCall> calls) {
|
void validateOutgoingMethodCalls(List<MethodCall> calls) {
|
||||||
expect(outgoingCalls.length, calls.length);
|
expect(outgoingCalls.length, calls.length);
|
||||||
bool hasError = false;
|
bool hasError = false;
|
||||||
|
@ -3107,7 +3107,7 @@ Future<void> _testLongPressDraggableHapticFeedback({ required WidgetTester teste
|
|||||||
bool onDragStartedCalled = false;
|
bool onDragStartedCalled = false;
|
||||||
|
|
||||||
int hapticFeedbackCalls = 0;
|
int hapticFeedbackCalls = 0;
|
||||||
SystemChannels.platform.setMockMethodCallHandler((MethodCall methodCall) async {
|
tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async {
|
||||||
if (methodCall.method == 'HapticFeedback.vibrate') {
|
if (methodCall.method == 'HapticFeedback.vibrate') {
|
||||||
hapticFeedbackCalls++;
|
hapticFeedbackCalls++;
|
||||||
}
|
}
|
||||||
|
@ -79,7 +79,7 @@ void main() {
|
|||||||
|
|
||||||
// Populate a fake clipboard.
|
// Populate a fake clipboard.
|
||||||
const String clipboardContent = ' ';
|
const String clipboardContent = ' ';
|
||||||
SystemChannels.platform.setMockMethodCallHandler((MethodCall methodCall) async {
|
tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async {
|
||||||
if (methodCall.method == 'Clipboard.getData')
|
if (methodCall.method == 'Clipboard.getData')
|
||||||
return const <String, dynamic>{'text': clipboardContent};
|
return const <String, dynamic>{'text': clipboardContent};
|
||||||
return null;
|
return null;
|
||||||
@ -131,7 +131,7 @@ void main() {
|
|||||||
|
|
||||||
// Populate a fake clipboard.
|
// Populate a fake clipboard.
|
||||||
const String clipboardContent = ' ';
|
const String clipboardContent = ' ';
|
||||||
SystemChannels.platform.setMockMethodCallHandler((MethodCall methodCall) async {
|
tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async {
|
||||||
if (methodCall.method == 'Clipboard.getData')
|
if (methodCall.method == 'Clipboard.getData')
|
||||||
return const <String, dynamic>{'text': clipboardContent};
|
return const <String, dynamic>{'text': clipboardContent};
|
||||||
return null;
|
return null;
|
||||||
@ -853,7 +853,7 @@ void main() {
|
|||||||
|
|
||||||
// Populate a fake clipboard.
|
// Populate a fake clipboard.
|
||||||
const String clipboardContent = 'Hello world!';
|
const String clipboardContent = 'Hello world!';
|
||||||
SystemChannels.platform.setMockMethodCallHandler((MethodCall methodCall) async {
|
tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async {
|
||||||
if (methodCall.method == 'Clipboard.getData')
|
if (methodCall.method == 'Clipboard.getData')
|
||||||
return const <String, dynamic>{'text': clipboardContent};
|
return const <String, dynamic>{'text': clipboardContent};
|
||||||
return null;
|
return null;
|
||||||
@ -911,7 +911,7 @@ void main() {
|
|||||||
|
|
||||||
// Populate a fake clipboard.
|
// Populate a fake clipboard.
|
||||||
const String clipboardContent = 'Hello world!';
|
const String clipboardContent = 'Hello world!';
|
||||||
SystemChannels.platform.setMockMethodCallHandler((MethodCall methodCall) async {
|
tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async {
|
||||||
if (methodCall.method == 'Clipboard.getData')
|
if (methodCall.method == 'Clipboard.getData')
|
||||||
return const <String, dynamic>{'text': clipboardContent};
|
return const <String, dynamic>{'text': clipboardContent};
|
||||||
return null;
|
return null;
|
||||||
|
@ -65,9 +65,9 @@ class MockClipboard {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
TestWidgetsFlutterBinding.ensureInitialized();
|
|
||||||
final MockClipboard mockClipboard = MockClipboard();
|
final MockClipboard mockClipboard = MockClipboard();
|
||||||
SystemChannels.platform.setMockMethodCallHandler(mockClipboard.handleMethodCall);
|
(TestWidgetsFlutterBinding.ensureInitialized() as TestWidgetsFlutterBinding)
|
||||||
|
.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, mockClipboard.handleMethodCall);
|
||||||
|
|
||||||
setUp(() async {
|
setUp(() async {
|
||||||
debugResetSemanticsIdCounter();
|
debugResetSemanticsIdCounter();
|
||||||
@ -1982,7 +1982,7 @@ void main() {
|
|||||||
await tester.pump(); // An extra pump to allow focus request to go through.
|
await tester.pump(); // An extra pump to allow focus request to go through.
|
||||||
|
|
||||||
final List<MethodCall> log = <MethodCall>[];
|
final List<MethodCall> log = <MethodCall>[];
|
||||||
SystemChannels.textInput.setMockMethodCallHandler((MethodCall methodCall) async {
|
tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.textInput, (MethodCall methodCall) async {
|
||||||
log.add(methodCall);
|
log.add(methodCall);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -3234,7 +3234,7 @@ void main() {
|
|||||||
// Regression test for https://github.com/flutter/flutter/issues/22212.
|
// Regression test for https://github.com/flutter/flutter/issues/22212.
|
||||||
|
|
||||||
final List<MethodCall> log = <MethodCall>[];
|
final List<MethodCall> log = <MethodCall>[];
|
||||||
SystemChannels.textInput.setMockMethodCallHandler((MethodCall methodCall) async {
|
tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.textInput, (MethodCall methodCall) async {
|
||||||
log.add(methodCall);
|
log.add(methodCall);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -3265,7 +3265,7 @@ void main() {
|
|||||||
|
|
||||||
testWidgets('location of widget is sent on show keyboard', (WidgetTester tester) async {
|
testWidgets('location of widget is sent on show keyboard', (WidgetTester tester) async {
|
||||||
final List<MethodCall> log = <MethodCall>[];
|
final List<MethodCall> log = <MethodCall>[];
|
||||||
SystemChannels.textInput.setMockMethodCallHandler((MethodCall methodCall) async {
|
tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.textInput, (MethodCall methodCall) async {
|
||||||
log.add(methodCall);
|
log.add(methodCall);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -3302,7 +3302,7 @@ void main() {
|
|||||||
|
|
||||||
testWidgets('transform and size is reset when text connection opens', (WidgetTester tester) async {
|
testWidgets('transform and size is reset when text connection opens', (WidgetTester tester) async {
|
||||||
final List<MethodCall> log = <MethodCall>[];
|
final List<MethodCall> log = <MethodCall>[];
|
||||||
SystemChannels.textInput.setMockMethodCallHandler((MethodCall methodCall) async {
|
tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.textInput, (MethodCall methodCall) async {
|
||||||
log.add(methodCall);
|
log.add(methodCall);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -3390,7 +3390,7 @@ void main() {
|
|||||||
|
|
||||||
testWidgets('size and transform are sent when they change', (WidgetTester tester) async {
|
testWidgets('size and transform are sent when they change', (WidgetTester tester) async {
|
||||||
final List<MethodCall> log = <MethodCall>[];
|
final List<MethodCall> log = <MethodCall>[];
|
||||||
SystemChannels.textInput.setMockMethodCallHandler((MethodCall methodCall) async {
|
tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.textInput, (MethodCall methodCall) async {
|
||||||
log.add(methodCall);
|
log.add(methodCall);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -3432,7 +3432,7 @@ void main() {
|
|||||||
|
|
||||||
testWidgets('text styling info is sent on show keyboard', (WidgetTester tester) async {
|
testWidgets('text styling info is sent on show keyboard', (WidgetTester tester) async {
|
||||||
final List<MethodCall> log = <MethodCall>[];
|
final List<MethodCall> log = <MethodCall>[];
|
||||||
SystemChannels.textInput.setMockMethodCallHandler((MethodCall methodCall) async {
|
tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.textInput, (MethodCall methodCall) async {
|
||||||
log.add(methodCall);
|
log.add(methodCall);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -3519,7 +3519,7 @@ void main() {
|
|||||||
await tester.showKeyboard(find.byType(EditableText));
|
await tester.showKeyboard(find.byType(EditableText));
|
||||||
|
|
||||||
final List<MethodCall> log = <MethodCall>[];
|
final List<MethodCall> log = <MethodCall>[];
|
||||||
SystemChannels.textInput.setMockMethodCallHandler((MethodCall methodCall) async {
|
tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.textInput, (MethodCall methodCall) async {
|
||||||
log.add(methodCall);
|
log.add(methodCall);
|
||||||
});
|
});
|
||||||
setState(() {
|
setState(() {
|
||||||
@ -3748,7 +3748,7 @@ void main() {
|
|||||||
// Regression test for https://github.com/flutter/flutter/issues/22212.
|
// Regression test for https://github.com/flutter/flutter/issues/22212.
|
||||||
|
|
||||||
final List<MethodCall> log = <MethodCall>[];
|
final List<MethodCall> log = <MethodCall>[];
|
||||||
SystemChannels.textInput.setMockMethodCallHandler((MethodCall methodCall) async {
|
tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.textInput, (MethodCall methodCall) async {
|
||||||
log.add(methodCall);
|
log.add(methodCall);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -5720,7 +5720,7 @@ void main() {
|
|||||||
testWidgets('Synchronous test of local and remote editing values', (WidgetTester tester) async {
|
testWidgets('Synchronous test of local and remote editing values', (WidgetTester tester) async {
|
||||||
// Regression test for https://github.com/flutter/flutter/issues/65059
|
// Regression test for https://github.com/flutter/flutter/issues/65059
|
||||||
final List<MethodCall> log = <MethodCall>[];
|
final List<MethodCall> log = <MethodCall>[];
|
||||||
SystemChannels.textInput.setMockMethodCallHandler((MethodCall methodCall) async {
|
tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.textInput, (MethodCall methodCall) async {
|
||||||
log.add(methodCall);
|
log.add(methodCall);
|
||||||
});
|
});
|
||||||
final TextInputFormatter formatter = TextInputFormatter.withFunction((TextEditingValue oldValue, TextEditingValue newValue) {
|
final TextInputFormatter formatter = TextInputFormatter.withFunction((TextEditingValue oldValue, TextEditingValue newValue) {
|
||||||
@ -5848,7 +5848,7 @@ void main() {
|
|||||||
testWidgets('Send text input state to engine when the input formatter rejects user input', (WidgetTester tester) async {
|
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
|
// Regression test for https://github.com/flutter/flutter/issues/67828
|
||||||
final List<MethodCall> log = <MethodCall>[];
|
final List<MethodCall> log = <MethodCall>[];
|
||||||
SystemChannels.textInput.setMockMethodCallHandler((MethodCall methodCall) async {
|
tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.textInput, (MethodCall methodCall) async {
|
||||||
log.add(methodCall);
|
log.add(methodCall);
|
||||||
});
|
});
|
||||||
final TextInputFormatter formatter = TextInputFormatter.withFunction((TextEditingValue oldValue, TextEditingValue newValue) {
|
final TextInputFormatter formatter = TextInputFormatter.withFunction((TextEditingValue oldValue, TextEditingValue newValue) {
|
||||||
@ -5927,7 +5927,7 @@ void main() {
|
|||||||
testWidgets('Repeatedly receiving [TextEditingValue] will not trigger a keyboard request', (WidgetTester tester) async {
|
testWidgets('Repeatedly receiving [TextEditingValue] will not trigger a keyboard request', (WidgetTester tester) async {
|
||||||
// Regression test for https://github.com/flutter/flutter/issues/66036
|
// Regression test for https://github.com/flutter/flutter/issues/66036
|
||||||
final List<MethodCall> log = <MethodCall>[];
|
final List<MethodCall> log = <MethodCall>[];
|
||||||
SystemChannels.textInput.setMockMethodCallHandler((MethodCall methodCall) async {
|
tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.textInput, (MethodCall methodCall) async {
|
||||||
log.add(methodCall);
|
log.add(methodCall);
|
||||||
});
|
});
|
||||||
final TextEditingController controller = TextEditingController();
|
final TextEditingController controller = TextEditingController();
|
||||||
@ -6048,7 +6048,7 @@ void main() {
|
|||||||
testWidgets('TextEditingController.clear() behavior test', (WidgetTester tester) async {
|
testWidgets('TextEditingController.clear() behavior test', (WidgetTester tester) async {
|
||||||
// Regression test for https://github.com/flutter/flutter/issues/66316
|
// Regression test for https://github.com/flutter/flutter/issues/66316
|
||||||
final List<MethodCall> log = <MethodCall>[];
|
final List<MethodCall> log = <MethodCall>[];
|
||||||
SystemChannels.textInput.setMockMethodCallHandler((MethodCall methodCall) async {
|
tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.textInput, (MethodCall methodCall) async {
|
||||||
log.add(methodCall);
|
log.add(methodCall);
|
||||||
});
|
});
|
||||||
final TextEditingController controller = TextEditingController();
|
final TextEditingController controller = TextEditingController();
|
||||||
|
@ -159,7 +159,7 @@ void main() {
|
|||||||
testWidgets('ModalBarrier plays system alert sound when user tries to dismiss it', (WidgetTester tester) async {
|
testWidgets('ModalBarrier plays system alert sound when user tries to dismiss it', (WidgetTester tester) async {
|
||||||
final List<String> playedSystemSounds = <String>[];
|
final List<String> playedSystemSounds = <String>[];
|
||||||
try {
|
try {
|
||||||
SystemChannels.platform.setMockMethodCallHandler((MethodCall methodCall) async {
|
tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async {
|
||||||
if (methodCall.method == 'SystemSound.play')
|
if (methodCall.method == 'SystemSound.play')
|
||||||
playedSystemSounds.add(methodCall.arguments as String);
|
playedSystemSounds.add(methodCall.arguments as String);
|
||||||
});
|
});
|
||||||
@ -176,7 +176,7 @@ void main() {
|
|||||||
await tester.tap(find.text('target'), warnIfMissed: false);
|
await tester.tap(find.text('target'), warnIfMissed: false);
|
||||||
await tester.pumpWidget(subject);
|
await tester.pumpWidget(subject);
|
||||||
} finally {
|
} finally {
|
||||||
SystemChannels.platform.setMockMethodCallHandler(null);
|
tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, null);
|
||||||
}
|
}
|
||||||
expect(playedSystemSounds, hasLength(1));
|
expect(playedSystemSounds, hasLength(1));
|
||||||
expect(playedSystemSounds[0], SystemSoundType.alert.toString());
|
expect(playedSystemSounds[0], SystemSoundType.alert.toString());
|
||||||
|
@ -1591,7 +1591,7 @@ void main() {
|
|||||||
final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse);
|
final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse);
|
||||||
await gesture.addPointer(location: const Offset(100, 100));
|
await gesture.addPointer(location: const Offset(100, 100));
|
||||||
addTearDown(gesture.removePointer);
|
addTearDown(gesture.removePointer);
|
||||||
SystemChannels.mouseCursor.setMockMethodCallHandler((_) async {
|
tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.mouseCursor, (_) async {
|
||||||
logCursors.add('cursor');
|
logCursors.add('cursor');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1075,7 +1075,7 @@ void main() {
|
|||||||
await tester.pump();
|
await tester.pump();
|
||||||
|
|
||||||
late int lastPlatformViewTextClient;
|
late int lastPlatformViewTextClient;
|
||||||
SystemChannels.textInput.setMockMethodCallHandler((MethodCall call) {
|
tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.textInput, (MethodCall call) {
|
||||||
if (call.method == 'TextInput.setPlatformViewClient') {
|
if (call.method == 'TextInput.setPlatformViewClient') {
|
||||||
lastPlatformViewTextClient = call.arguments as int;
|
lastPlatformViewTextClient = call.arguments as int;
|
||||||
}
|
}
|
||||||
|
@ -55,7 +55,7 @@ void main() {
|
|||||||
|
|
||||||
final List<MethodCall> log = <MethodCall>[];
|
final List<MethodCall> log = <MethodCall>[];
|
||||||
|
|
||||||
SystemChannels.navigation.setMockMethodCallHandler((MethodCall methodCall) async {
|
tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.navigation, (MethodCall methodCall) async {
|
||||||
log.add(methodCall);
|
log.add(methodCall);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -110,7 +110,7 @@ void main() {
|
|||||||
|
|
||||||
testWidgets('Navigator does not report route name by default', (WidgetTester tester) async {
|
testWidgets('Navigator does not report route name by default', (WidgetTester tester) async {
|
||||||
final List<MethodCall> log = <MethodCall>[];
|
final List<MethodCall> log = <MethodCall>[];
|
||||||
SystemChannels.navigation.setMockMethodCallHandler((MethodCall methodCall) async {
|
tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.navigation, (MethodCall methodCall) async {
|
||||||
log.add(methodCall);
|
log.add(methodCall);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -160,7 +160,7 @@ void main() {
|
|||||||
|
|
||||||
final List<MethodCall> log = <MethodCall>[];
|
final List<MethodCall> log = <MethodCall>[];
|
||||||
|
|
||||||
SystemChannels.navigation.setMockMethodCallHandler((MethodCall methodCall) async {
|
tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.navigation, (MethodCall methodCall) async {
|
||||||
log.add(methodCall);
|
log.add(methodCall);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -215,7 +215,7 @@ void main() {
|
|||||||
|
|
||||||
testWidgets('Nameless routes should send platform messages', (WidgetTester tester) async {
|
testWidgets('Nameless routes should send platform messages', (WidgetTester tester) async {
|
||||||
final List<MethodCall> log = <MethodCall>[];
|
final List<MethodCall> log = <MethodCall>[];
|
||||||
SystemChannels.navigation.setMockMethodCallHandler((MethodCall methodCall) async {
|
tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.navigation, (MethodCall methodCall) async {
|
||||||
log.add(methodCall);
|
log.add(methodCall);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -257,7 +257,7 @@ void main() {
|
|||||||
|
|
||||||
testWidgets('PlatformRouteInformationProvider reports URL', (WidgetTester tester) async {
|
testWidgets('PlatformRouteInformationProvider reports URL', (WidgetTester tester) async {
|
||||||
final List<MethodCall> log = <MethodCall>[];
|
final List<MethodCall> log = <MethodCall>[];
|
||||||
SystemChannels.navigation.setMockMethodCallHandler((MethodCall methodCall) async {
|
tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.navigation, (MethodCall methodCall) async {
|
||||||
log.add(methodCall);
|
log.add(methodCall);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -124,7 +124,7 @@ double getOpacity(WidgetTester tester, Finder finder) {
|
|||||||
void main() {
|
void main() {
|
||||||
TestWidgetsFlutterBinding.ensureInitialized();
|
TestWidgetsFlutterBinding.ensureInitialized();
|
||||||
final MockClipboard mockClipboard = MockClipboard();
|
final MockClipboard mockClipboard = MockClipboard();
|
||||||
SystemChannels.platform.setMockMethodCallHandler(mockClipboard.handleMethodCall);
|
TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, mockClipboard.handleMethodCall);
|
||||||
|
|
||||||
const String kThreeLines =
|
const String kThreeLines =
|
||||||
'First line of text is\n'
|
'First line of text is\n'
|
||||||
@ -1665,7 +1665,7 @@ void main() {
|
|||||||
final FocusNode focusNode = FocusNode();
|
final FocusNode focusNode = FocusNode();
|
||||||
|
|
||||||
String clipboardContent = '';
|
String clipboardContent = '';
|
||||||
SystemChannels.platform.setMockMethodCallHandler((MethodCall methodCall) async {
|
tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async {
|
||||||
if (methodCall.method == 'Clipboard.setData')
|
if (methodCall.method == 'Clipboard.setData')
|
||||||
clipboardContent = methodCall.arguments['text'] as String;
|
clipboardContent = methodCall.arguments['text'] as String;
|
||||||
else if (methodCall.method == 'Clipboard.getData')
|
else if (methodCall.method == 'Clipboard.getData')
|
||||||
|
@ -19,15 +19,15 @@ class MockClipboard {
|
|||||||
'text': null,
|
'text': null,
|
||||||
};
|
};
|
||||||
|
|
||||||
Future<dynamic> handleMethodCall(MethodCall methodCall) async {
|
Future<Object?> handleMethodCall(MethodCall methodCall) async {
|
||||||
switch (methodCall.method) {
|
switch (methodCall.method) {
|
||||||
case 'Clipboard.getData':
|
case 'Clipboard.getData':
|
||||||
if (getDataThrows) {
|
if (getDataThrows)
|
||||||
throw Exception();
|
throw Exception();
|
||||||
}
|
|
||||||
return _clipboardData;
|
return _clipboardData;
|
||||||
case 'Clipboard.setData':
|
case 'Clipboard.setData':
|
||||||
_clipboardData = methodCall.arguments;
|
_clipboardData = methodCall.arguments;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -758,11 +758,11 @@ void main() {
|
|||||||
group('when Clipboard fails', () {
|
group('when Clipboard fails', () {
|
||||||
setUp(() {
|
setUp(() {
|
||||||
final MockClipboard mockClipboard = MockClipboard(getDataThrows: true);
|
final MockClipboard mockClipboard = MockClipboard(getDataThrows: true);
|
||||||
SystemChannels.platform.setMockMethodCallHandler(mockClipboard.handleMethodCall);
|
TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, mockClipboard.handleMethodCall);
|
||||||
});
|
});
|
||||||
|
|
||||||
tearDown(() {
|
tearDown(() {
|
||||||
SystemChannels.platform.setMockMethodCallHandler(null);
|
TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, null);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Clipboard API failure is gracefully recovered from', () async {
|
test('Clipboard API failure is gracefully recovered from', () async {
|
||||||
@ -778,11 +778,11 @@ void main() {
|
|||||||
final MockClipboard mockClipboard = MockClipboard();
|
final MockClipboard mockClipboard = MockClipboard();
|
||||||
|
|
||||||
setUp(() {
|
setUp(() {
|
||||||
SystemChannels.platform.setMockMethodCallHandler(mockClipboard.handleMethodCall);
|
TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, mockClipboard.handleMethodCall);
|
||||||
});
|
});
|
||||||
|
|
||||||
tearDown(() {
|
tearDown(() {
|
||||||
SystemChannels.platform.setMockMethodCallHandler(null);
|
TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, null);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('update sets value based on clipboard contents', () async {
|
test('update sets value based on clipboard contents', () async {
|
||||||
|
@ -36,7 +36,7 @@ void main() {
|
|||||||
testWidgets('should not pass "null" to setApplicationSwitcherDescription', (WidgetTester tester) async {
|
testWidgets('should not pass "null" to setApplicationSwitcherDescription', (WidgetTester tester) async {
|
||||||
final List<MethodCall> log = <MethodCall>[];
|
final List<MethodCall> log = <MethodCall>[];
|
||||||
|
|
||||||
SystemChannels.platform.setMockMethodCallHandler((MethodCall methodCall) async {
|
tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async {
|
||||||
log.add(methodCall);
|
log.add(methodCall);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ const String _extensionMethodName = 'driver';
|
|||||||
/// eventually completes to a string response.
|
/// eventually completes to a string response.
|
||||||
typedef DataHandler = Future<String> Function(String? message);
|
typedef DataHandler = Future<String> Function(String? message);
|
||||||
|
|
||||||
class _DriverBinding extends BindingBase with SchedulerBinding, ServicesBinding, GestureBinding, PaintingBinding, SemanticsBinding, RendererBinding, WidgetsBinding {
|
class _DriverBinding extends BindingBase with SchedulerBinding, ServicesBinding, GestureBinding, PaintingBinding, SemanticsBinding, RendererBinding, WidgetsBinding, TestDefaultBinaryMessengerBinding {
|
||||||
_DriverBinding(this._handler, this._silenceErrors, this._enableTextEntryEmulation, this.finders, this.commands);
|
_DriverBinding(this._handler, this._silenceErrors, this._enableTextEntryEmulation, this.finders, this.commands);
|
||||||
|
|
||||||
final DataHandler? _handler;
|
final DataHandler? _handler;
|
||||||
@ -51,11 +51,6 @@ class _DriverBinding extends BindingBase with SchedulerBinding, ServicesBinding,
|
|||||||
registerWebServiceExtension(extension.call);
|
registerWebServiceExtension(extension.call);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
BinaryMessenger createBinaryMessenger() {
|
|
||||||
return TestDefaultBinaryMessenger(super.createBinaryMessenger());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Enables Flutter Driver VM service extension.
|
/// Enables Flutter Driver VM service extension.
|
||||||
@ -330,11 +325,11 @@ class FlutterDriverExtension with DeserializeFinderFactory, CreateFinderFactory,
|
|||||||
registerTextInput();
|
registerTextInput();
|
||||||
}
|
}
|
||||||
|
|
||||||
for(final FinderExtension finder in finders) {
|
for (final FinderExtension finder in finders) {
|
||||||
_finderExtensions[finder.finderType] = finder;
|
_finderExtensions[finder.finderType] = finder;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(final CommandExtension command in commands) {
|
for (final CommandExtension command in commands) {
|
||||||
_commandExtensions[command.commandKind] = command;
|
_commandExtensions[command.commandKind] = command;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -418,7 +413,7 @@ class FlutterDriverExtension with DeserializeFinderFactory, CreateFinderFactory,
|
|||||||
@override
|
@override
|
||||||
Command deserializeCommand(Map<String, String> params, DeserializeFinderFactory finderFactory) {
|
Command deserializeCommand(Map<String, String> params, DeserializeFinderFactory finderFactory) {
|
||||||
final String? kind = params['command'];
|
final String? kind = params['command'];
|
||||||
if(_commandExtensions.containsKey(kind)) {
|
if (_commandExtensions.containsKey(kind)) {
|
||||||
return _commandExtensions[kind]!.deserialize(params, finderFactory, this);
|
return _commandExtensions[kind]!.deserialize(params, finderFactory, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -434,7 +429,7 @@ class FlutterDriverExtension with DeserializeFinderFactory, CreateFinderFactory,
|
|||||||
@override
|
@override
|
||||||
Future<Result> handleCommand(Command command, WidgetController prober, CreateFinderFactory finderFactory) {
|
Future<Result> handleCommand(Command command, WidgetController prober, CreateFinderFactory finderFactory) {
|
||||||
final String kind = command.kind;
|
final String kind = command.kind;
|
||||||
if(_commandExtensions.containsKey(kind)) {
|
if (_commandExtensions.containsKey(kind)) {
|
||||||
return _commandExtensions[kind]!.call(command, prober, finderFactory, this);
|
return _commandExtensions[kind]!.call(command, prober, finderFactory, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -279,7 +279,7 @@ void main() {
|
|||||||
'waiting for NoPendingPlatformMessages returns until a single method channel call returns', (WidgetTester tester) async {
|
'waiting for NoPendingPlatformMessages returns until a single method channel call returns', (WidgetTester tester) async {
|
||||||
const MethodChannel channel = MethodChannel('helloChannel', JSONMethodCodec());
|
const MethodChannel channel = MethodChannel('helloChannel', JSONMethodCodec());
|
||||||
const MessageCodec<dynamic> jsonMessage = JSONMessageCodec();
|
const MessageCodec<dynamic> jsonMessage = JSONMessageCodec();
|
||||||
ServicesBinding.instance!.defaultBinaryMessenger.setMockMessageHandler(
|
tester.binding.defaultBinaryMessenger.setMockMessageHandler(
|
||||||
'helloChannel', (ByteData? message) {
|
'helloChannel', (ByteData? message) {
|
||||||
return Future<ByteData>.delayed(
|
return Future<ByteData>.delayed(
|
||||||
const Duration(milliseconds: 10),
|
const Duration(milliseconds: 10),
|
||||||
@ -313,7 +313,7 @@ void main() {
|
|||||||
const MessageCodec<dynamic> jsonMessage = JSONMessageCodec();
|
const MessageCodec<dynamic> jsonMessage = JSONMessageCodec();
|
||||||
// Configures channel 1
|
// Configures channel 1
|
||||||
const MethodChannel channel1 = MethodChannel('helloChannel1', JSONMethodCodec());
|
const MethodChannel channel1 = MethodChannel('helloChannel1', JSONMethodCodec());
|
||||||
ServicesBinding.instance!.defaultBinaryMessenger.setMockMessageHandler(
|
tester.binding.defaultBinaryMessenger.setMockMessageHandler(
|
||||||
'helloChannel1', (ByteData? message) {
|
'helloChannel1', (ByteData? message) {
|
||||||
return Future<ByteData>.delayed(
|
return Future<ByteData>.delayed(
|
||||||
const Duration(milliseconds: 10),
|
const Duration(milliseconds: 10),
|
||||||
@ -322,7 +322,7 @@ void main() {
|
|||||||
|
|
||||||
// Configures channel 2
|
// Configures channel 2
|
||||||
const MethodChannel channel2 = MethodChannel('helloChannel2', JSONMethodCodec());
|
const MethodChannel channel2 = MethodChannel('helloChannel2', JSONMethodCodec());
|
||||||
ServicesBinding.instance!.defaultBinaryMessenger.setMockMessageHandler(
|
tester.binding.defaultBinaryMessenger.setMockMessageHandler(
|
||||||
'helloChannel2', (ByteData? message) {
|
'helloChannel2', (ByteData? message) {
|
||||||
return Future<ByteData>.delayed(
|
return Future<ByteData>.delayed(
|
||||||
const Duration(milliseconds: 20),
|
const Duration(milliseconds: 20),
|
||||||
@ -362,7 +362,7 @@ void main() {
|
|||||||
const MessageCodec<dynamic> jsonMessage = JSONMessageCodec();
|
const MessageCodec<dynamic> jsonMessage = JSONMessageCodec();
|
||||||
// Configures channel 1
|
// Configures channel 1
|
||||||
const MethodChannel channel1 = MethodChannel('helloChannel1', JSONMethodCodec());
|
const MethodChannel channel1 = MethodChannel('helloChannel1', JSONMethodCodec());
|
||||||
ServicesBinding.instance!.defaultBinaryMessenger.setMockMessageHandler(
|
tester.binding.defaultBinaryMessenger.setMockMessageHandler(
|
||||||
'helloChannel1', (ByteData? message) {
|
'helloChannel1', (ByteData? message) {
|
||||||
return Future<ByteData>.delayed(
|
return Future<ByteData>.delayed(
|
||||||
const Duration(milliseconds: 10),
|
const Duration(milliseconds: 10),
|
||||||
@ -371,7 +371,7 @@ void main() {
|
|||||||
|
|
||||||
// Configures channel 2
|
// Configures channel 2
|
||||||
const MethodChannel channel2 = MethodChannel('helloChannel2', JSONMethodCodec());
|
const MethodChannel channel2 = MethodChannel('helloChannel2', JSONMethodCodec());
|
||||||
ServicesBinding.instance!.defaultBinaryMessenger.setMockMessageHandler(
|
tester.binding.defaultBinaryMessenger.setMockMessageHandler(
|
||||||
'helloChannel2', (ByteData? message) {
|
'helloChannel2', (ByteData? message) {
|
||||||
return Future<ByteData>.delayed(
|
return Future<ByteData>.delayed(
|
||||||
const Duration(milliseconds: 20),
|
const Duration(milliseconds: 20),
|
||||||
@ -413,7 +413,7 @@ void main() {
|
|||||||
const MessageCodec<dynamic> jsonMessage = JSONMessageCodec();
|
const MessageCodec<dynamic> jsonMessage = JSONMessageCodec();
|
||||||
// Configures channel 1
|
// Configures channel 1
|
||||||
const MethodChannel channel1 = MethodChannel('helloChannel1', JSONMethodCodec());
|
const MethodChannel channel1 = MethodChannel('helloChannel1', JSONMethodCodec());
|
||||||
ServicesBinding.instance!.defaultBinaryMessenger.setMockMessageHandler(
|
tester.binding.defaultBinaryMessenger.setMockMessageHandler(
|
||||||
'helloChannel1', (ByteData? message) {
|
'helloChannel1', (ByteData? message) {
|
||||||
return Future<ByteData>.delayed(
|
return Future<ByteData>.delayed(
|
||||||
const Duration(milliseconds: 20),
|
const Duration(milliseconds: 20),
|
||||||
@ -422,7 +422,7 @@ void main() {
|
|||||||
|
|
||||||
// Configures channel 2
|
// Configures channel 2
|
||||||
const MethodChannel channel2 = MethodChannel('helloChannel2', JSONMethodCodec());
|
const MethodChannel channel2 = MethodChannel('helloChannel2', JSONMethodCodec());
|
||||||
ServicesBinding.instance!.defaultBinaryMessenger.setMockMessageHandler(
|
tester.binding.defaultBinaryMessenger.setMockMessageHandler(
|
||||||
'helloChannel2', (ByteData? message) {
|
'helloChannel2', (ByteData? message) {
|
||||||
return Future<ByteData>.delayed(
|
return Future<ByteData>.delayed(
|
||||||
const Duration(milliseconds: 10),
|
const Duration(milliseconds: 10),
|
||||||
|
@ -61,6 +61,7 @@ export 'src/all_elements.dart';
|
|||||||
export 'src/animation_sheet.dart';
|
export 'src/animation_sheet.dart';
|
||||||
export 'src/binding.dart';
|
export 'src/binding.dart';
|
||||||
export 'src/controller.dart';
|
export 'src/controller.dart';
|
||||||
|
export 'src/deprecated.dart';
|
||||||
export 'src/event_simulation.dart';
|
export 'src/event_simulation.dart';
|
||||||
export 'src/finders.dart';
|
export 'src/finders.dart';
|
||||||
export 'src/frame_timing_summarizer.dart';
|
export 'src/frame_timing_summarizer.dart';
|
||||||
@ -73,6 +74,7 @@ export 'src/restoration.dart';
|
|||||||
export 'src/stack_manipulation.dart';
|
export 'src/stack_manipulation.dart';
|
||||||
export 'src/test_async_utils.dart';
|
export 'src/test_async_utils.dart';
|
||||||
export 'src/test_compat.dart';
|
export 'src/test_compat.dart';
|
||||||
|
export 'src/test_default_binary_messenger.dart';
|
||||||
export 'src/test_exception_reporter.dart';
|
export 'src/test_exception_reporter.dart';
|
||||||
export 'src/test_pointer.dart';
|
export 'src/test_pointer.dart';
|
||||||
export 'src/test_text_input.dart';
|
export 'src/test_text_input.dart';
|
||||||
|
@ -13,8 +13,8 @@ import 'package:path/path.dart' as path;
|
|||||||
// ignore: deprecated_member_use
|
// ignore: deprecated_member_use
|
||||||
import 'package:test_api/test_api.dart' as test_package;
|
import 'package:test_api/test_api.dart' as test_package;
|
||||||
|
|
||||||
|
|
||||||
import 'binding.dart';
|
import 'binding.dart';
|
||||||
|
import 'deprecated.dart';
|
||||||
|
|
||||||
/// Ensure the [WidgetsBinding] is initialized.
|
/// Ensure the [WidgetsBinding] is initialized.
|
||||||
WidgetsBinding ensureInitialized([@visibleForTesting Map<String, String>? environment]) {
|
WidgetsBinding ensureInitialized([@visibleForTesting Map<String, String>? environment]) {
|
||||||
|
@ -15,8 +15,7 @@ import 'package:flutter/services.dart';
|
|||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
import 'package:flutter_test/flutter_test.dart' show TestWindow;
|
import 'package:flutter_test/flutter_test.dart' show TestWindow;
|
||||||
import 'package:stack_trace/stack_trace.dart' as stack_trace;
|
import 'package:stack_trace/stack_trace.dart' as stack_trace;
|
||||||
// ignore: deprecated_member_use
|
import 'package:test_api/test_api.dart' as test_package; // ignore: deprecated_member_use
|
||||||
import 'package:test_api/test_api.dart' as test_package;
|
|
||||||
import 'package:vector_math/vector_math_64.dart';
|
import 'package:vector_math/vector_math_64.dart';
|
||||||
|
|
||||||
import '_binding_io.dart' if (dart.library.html) '_binding_web.dart' as binding;
|
import '_binding_io.dart' if (dart.library.html) '_binding_web.dart' as binding;
|
||||||
@ -25,6 +24,7 @@ import 'platform.dart';
|
|||||||
import 'restoration.dart';
|
import 'restoration.dart';
|
||||||
import 'stack_manipulation.dart';
|
import 'stack_manipulation.dart';
|
||||||
import 'test_async_utils.dart';
|
import 'test_async_utils.dart';
|
||||||
|
import 'test_default_binary_messenger.dart';
|
||||||
import 'test_exception_reporter.dart';
|
import 'test_exception_reporter.dart';
|
||||||
import 'test_text_input.dart';
|
import 'test_text_input.dart';
|
||||||
|
|
||||||
@ -79,74 +79,29 @@ enum TestBindingEventSource {
|
|||||||
|
|
||||||
const Size _kDefaultTestViewportSize = Size(800.0, 600.0);
|
const Size _kDefaultTestViewportSize = Size(800.0, 600.0);
|
||||||
|
|
||||||
/// A [BinaryMessenger] subclass that is used as the default binary messenger
|
/// Overrides the [ServicesBinding]'s binary messenger logic to use
|
||||||
/// under testing environment.
|
/// [TestDefaultBinaryMessenger].
|
||||||
///
|
///
|
||||||
/// It tracks status of data sent across the Flutter platform barrier, which is
|
/// Test bindings that are used by tests that mock message handlers for plugins
|
||||||
/// useful for testing frameworks to monitor and synchronize against the
|
/// should mix in this binding to enable the use of the
|
||||||
/// platform messages.
|
/// [TestDefaultBinaryMessenger] APIs.
|
||||||
class TestDefaultBinaryMessenger extends BinaryMessenger {
|
mixin TestDefaultBinaryMessengerBinding on BindingBase, ServicesBinding {
|
||||||
/// 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<Future<ByteData?>> _pendingMessages = <Future<ByteData?>>[];
|
|
||||||
|
|
||||||
/// The number of incomplete/pending calls sent to the platform channels.
|
|
||||||
int get pendingMessageCount => _pendingMessages.length;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<ByteData?>? send(String channel, ByteData? message) {
|
void initInstances() {
|
||||||
final Future<ByteData?>? resultFuture = delegate.send(channel, message);
|
super.initInstances();
|
||||||
if (resultFuture != null) {
|
_instance = this;
|
||||||
_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.
|
/// The current [TestDefaultBinaryMessengerBinding], if one has been created.
|
||||||
///
|
static TestDefaultBinaryMessengerBinding? get instance => _instance;
|
||||||
/// If a new platform message is sent after this method is called, this new
|
static TestDefaultBinaryMessengerBinding? _instance;
|
||||||
/// message is not tracked. Use with [pendingMessageCount] to guarantee no
|
|
||||||
/// pending message calls.
|
|
||||||
Future<void> get platformMessagesFinished {
|
|
||||||
return Future.wait<void>(_pendingMessages);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> handlePlatformMessage(
|
TestDefaultBinaryMessenger get defaultBinaryMessenger => super.defaultBinaryMessenger as TestDefaultBinaryMessenger;
|
||||||
String channel,
|
|
||||||
ByteData? data,
|
|
||||||
ui.PlatformMessageResponseCallback? callback,
|
|
||||||
) {
|
|
||||||
return delegate.handlePlatformMessage(channel, data, callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void setMessageHandler(String channel, MessageHandler? handler) {
|
TestDefaultBinaryMessenger createBinaryMessenger() {
|
||||||
delegate.setMessageHandler(channel, handler);
|
return TestDefaultBinaryMessenger(super.createBinaryMessenger());
|
||||||
}
|
|
||||||
|
|
||||||
@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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -171,7 +126,8 @@ abstract class TestWidgetsFlutterBinding extends BindingBase
|
|||||||
SemanticsBinding,
|
SemanticsBinding,
|
||||||
RendererBinding,
|
RendererBinding,
|
||||||
PaintingBinding,
|
PaintingBinding,
|
||||||
WidgetsBinding {
|
WidgetsBinding,
|
||||||
|
TestDefaultBinaryMessengerBinding {
|
||||||
|
|
||||||
/// Constructor for [TestWidgetsFlutterBinding].
|
/// Constructor for [TestWidgetsFlutterBinding].
|
||||||
///
|
///
|
||||||
@ -195,9 +151,15 @@ abstract class TestWidgetsFlutterBinding extends BindingBase
|
|||||||
|
|
||||||
/// Called by the test framework at the beginning of a widget test to
|
/// Called by the test framework at the beginning of a widget test to
|
||||||
/// prepare the binding for the next test.
|
/// prepare the binding for the next test.
|
||||||
|
///
|
||||||
|
/// If [registerTestTextInput] returns true when this method is called,
|
||||||
|
/// the [testTextInput] is configured to simulate the keyboard.
|
||||||
void reset() {
|
void reset() {
|
||||||
_restorationManager = null;
|
_restorationManager = null;
|
||||||
resetGestureBinding();
|
resetGestureBinding();
|
||||||
|
testTextInput.reset();
|
||||||
|
if (registerTestTextInput)
|
||||||
|
_testTextInput.register();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -237,7 +199,8 @@ abstract class TestWidgetsFlutterBinding extends BindingBase
|
|||||||
@protected
|
@protected
|
||||||
bool get overrideHttpClient => true;
|
bool get overrideHttpClient => true;
|
||||||
|
|
||||||
/// Determines whether the binding automatically registers [testTextInput].
|
/// Determines whether the binding automatically registers [testTextInput] as
|
||||||
|
/// a fake keyboard implementation.
|
||||||
///
|
///
|
||||||
/// Unit tests make use of this to mock out text input communication for
|
/// Unit tests make use of this to mock out text input communication for
|
||||||
/// widgets. An integration test would set this to false, to test real IME
|
/// widgets. An integration test would set this to false, to test real IME
|
||||||
@ -245,6 +208,19 @@ abstract class TestWidgetsFlutterBinding extends BindingBase
|
|||||||
///
|
///
|
||||||
/// [TestTextInput.isRegistered] reports whether the text input mock is
|
/// [TestTextInput.isRegistered] reports whether the text input mock is
|
||||||
/// registered or not.
|
/// registered or not.
|
||||||
|
///
|
||||||
|
/// Some of the properties and methods on [testTextInput] are only valid if
|
||||||
|
/// [registerTestTextInput] returns true when a test starts. If those
|
||||||
|
/// members are accessed when using a binding that sets this flag to false,
|
||||||
|
/// they will throw.
|
||||||
|
///
|
||||||
|
/// If this property returns true when a test ends, the [testTextInput] is
|
||||||
|
/// unregistered.
|
||||||
|
///
|
||||||
|
/// This property should not change the value it returns during the lifetime
|
||||||
|
/// of the binding. Changing the value of this property risks very confusing
|
||||||
|
/// behavior as the [TestTextInput] may be inconsistently registered or
|
||||||
|
/// unregistered.
|
||||||
@protected
|
@protected
|
||||||
bool get registerTestTextInput => true;
|
bool get registerTestTextInput => true;
|
||||||
|
|
||||||
@ -319,14 +295,6 @@ abstract class TestWidgetsFlutterBinding extends BindingBase
|
|||||||
binding.setupHttpOverrides();
|
binding.setupHttpOverrides();
|
||||||
}
|
}
|
||||||
_testTextInput = TestTextInput(onCleared: _resetFocusedEditable);
|
_testTextInput = TestTextInput(onCleared: _resetFocusedEditable);
|
||||||
if (registerTestTextInput) {
|
|
||||||
_testTextInput.register();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
BinaryMessenger createBinaryMessenger() {
|
|
||||||
return TestDefaultBinaryMessenger(super.createBinaryMessenger());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -515,12 +483,20 @@ abstract class TestWidgetsFlutterBinding extends BindingBase
|
|||||||
TestTextInput get testTextInput => _testTextInput;
|
TestTextInput get testTextInput => _testTextInput;
|
||||||
late TestTextInput _testTextInput;
|
late TestTextInput _testTextInput;
|
||||||
|
|
||||||
/// The current client of the onscreen keyboard. Callers must pump
|
/// The [State] of the current [EditableText] client of the onscreen keyboard.
|
||||||
/// an additional frame after setting this property to complete the
|
///
|
||||||
/// focus change.
|
/// Setting this property to a new value causes the given [EditableTextState]
|
||||||
|
/// to focus itself and request the keyboard to establish a
|
||||||
|
/// [TextInputConnection].
|
||||||
|
///
|
||||||
|
/// Callers must pump an additional frame after setting this property to
|
||||||
|
/// complete the focus change.
|
||||||
///
|
///
|
||||||
/// Instead of setting this directly, consider using
|
/// Instead of setting this directly, consider using
|
||||||
/// [WidgetTester.showKeyboard].
|
/// [WidgetTester.showKeyboard].
|
||||||
|
//
|
||||||
|
// TODO(ianh): We should just remove this property and move the call to
|
||||||
|
// requestKeyboard to the WidgetTester.showKeyboard method.
|
||||||
EditableTextState? get focusedEditable => _focusedEditable;
|
EditableTextState? get focusedEditable => _focusedEditable;
|
||||||
EditableTextState? _focusedEditable;
|
EditableTextState? _focusedEditable;
|
||||||
set focusedEditable(EditableTextState? value) {
|
set focusedEditable(EditableTextState? value) {
|
||||||
@ -799,6 +775,8 @@ abstract class TestWidgetsFlutterBinding extends BindingBase
|
|||||||
// alone so that we don't cause more spurious errors.
|
// alone so that we don't cause more spurious errors.
|
||||||
runApp(Container(key: UniqueKey(), child: _postTestMessage)); // Unmount any remaining widgets.
|
runApp(Container(key: UniqueKey(), child: _postTestMessage)); // Unmount any remaining widgets.
|
||||||
await pump();
|
await pump();
|
||||||
|
if (registerTestTextInput)
|
||||||
|
_testTextInput.unregister();
|
||||||
invariantTester();
|
invariantTester();
|
||||||
_verifyAutoUpdateGoldensUnset(autoUpdateGoldensBeforeTest && !isBrowser);
|
_verifyAutoUpdateGoldensUnset(autoUpdateGoldensBeforeTest && !isBrowser);
|
||||||
_verifyReportTestExceptionUnset(reportTestExceptionBeforeTest);
|
_verifyReportTestExceptionUnset(reportTestExceptionBeforeTest);
|
||||||
|
109
packages/flutter_test/lib/src/deprecated.dart
Normal file
109
packages/flutter_test/lib/src/deprecated.dart
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
// 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<T> on BasicMessageChannel<T> {
|
||||||
|
/// 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<T> Function(T? message)? handler) {
|
||||||
|
TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockDecodedMessageHandler<T>(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<dynamic>? 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);
|
||||||
|
}
|
||||||
|
}
|
@ -2,10 +2,13 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
import 'dart:async';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:flutter/foundation.dart' show kIsWeb;
|
import 'package:flutter/foundation.dart' show kIsWeb;
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
|
|
||||||
|
import 'binding.dart';
|
||||||
import 'test_async_utils.dart';
|
import 'test_async_utils.dart';
|
||||||
|
|
||||||
// TODO(gspencergoog): Replace this with more robust key simulation code once
|
// TODO(gspencergoog): Replace this with more robust key simulation code once
|
||||||
@ -640,22 +643,22 @@ class KeyEventSimulator {
|
|||||||
platform ??= Platform.operatingSystem;
|
platform ??= Platform.operatingSystem;
|
||||||
assert(_osIsSupported(platform!), 'Platform $platform not supported for key simulation');
|
assert(_osIsSupported(platform!), 'Platform $platform not supported for key simulation');
|
||||||
|
|
||||||
|
|
||||||
final Map<String, dynamic> data = getKeyData(key, platform: platform!, isDown: true, physicalKey: physicalKey, character: character);
|
final Map<String, dynamic> data = getKeyData(key, platform: platform!, isDown: true, physicalKey: physicalKey, character: character);
|
||||||
bool result = false;
|
final Completer<bool> result = Completer<bool>();
|
||||||
await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage(
|
await TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.handlePlatformMessage(
|
||||||
SystemChannels.keyEvent.name,
|
SystemChannels.keyEvent.name,
|
||||||
SystemChannels.keyEvent.codec.encodeMessage(data),
|
SystemChannels.keyEvent.codec.encodeMessage(data),
|
||||||
(ByteData? data) {
|
(ByteData? data) {
|
||||||
if (data == null) {
|
if (data == null) {
|
||||||
|
result.complete(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final Map<String, dynamic> decoded = SystemChannels.keyEvent.codec.decodeMessage(data) as Map<String, dynamic>;
|
final Map<String, dynamic> decoded = SystemChannels.keyEvent.codec.decodeMessage(data) as Map<String, dynamic>;
|
||||||
if (decoded['handled'] as bool) {
|
result.complete(decoded['handled'] as bool);
|
||||||
result = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
return result;
|
return result.future;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -681,7 +684,7 @@ class KeyEventSimulator {
|
|||||||
|
|
||||||
final Map<String, dynamic> data = getKeyData(key, platform: platform!, isDown: false, physicalKey: physicalKey);
|
final Map<String, dynamic> data = getKeyData(key, platform: platform!, isDown: false, physicalKey: physicalKey);
|
||||||
bool result = false;
|
bool result = false;
|
||||||
await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage(
|
await TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.handlePlatformMessage(
|
||||||
SystemChannels.keyEvent.name,
|
SystemChannels.keyEvent.name,
|
||||||
SystemChannels.keyEvent.codec.encodeMessage(data),
|
SystemChannels.keyEvent.codec.encodeMessage(data),
|
||||||
(ByteData? data) {
|
(ByteData? data) {
|
||||||
|
306
packages/flutter_test/lib/src/test_default_binary_messenger.dart
Normal file
306
packages/flutter_test/lib/src/test_default_binary_messenger.dart
Normal file
@ -0,0 +1,306 @@
|
|||||||
|
// 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<String, MessageHandler> _inboundHandlers = <String, MessageHandler>{};
|
||||||
|
|
||||||
|
/// 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<ByteData?> handlePlatformMessage(
|
||||||
|
String channel,
|
||||||
|
ByteData? data,
|
||||||
|
ui.PlatformMessageResponseCallback? callback,
|
||||||
|
) {
|
||||||
|
Future<ByteData?>? result;
|
||||||
|
if (_inboundHandlers.containsKey(channel))
|
||||||
|
result = _inboundHandlers[channel]!(data);
|
||||||
|
result ??= Future<ByteData?>.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<Future<ByteData?>> _pendingMessages = <Future<ByteData?>>[];
|
||||||
|
|
||||||
|
/// 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<String, MessageHandler> _outboundHandlers = <String, MessageHandler>{};
|
||||||
|
|
||||||
|
// The outbound callbacks that were actually registered, so that we
|
||||||
|
// can implement the [checkMockMessageHandler] method.
|
||||||
|
final Map<String, Object> _outboundHandlerIdentities = <String, Object>{};
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<ByteData?>? send(String channel, ByteData? message) {
|
||||||
|
final Future<ByteData?>? 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<void> get platformMessagesFinished {
|
||||||
|
return Future.wait<void>(_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<T>(BasicMessageChannel<T> channel, Future<T> 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<Object?>? 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;
|
||||||
|
}
|
@ -8,12 +8,28 @@ import 'package:flutter/foundation.dart';
|
|||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_test/flutter_test.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;
|
export 'package:flutter/services.dart' show TextEditingValue, TextInputAction;
|
||||||
|
|
||||||
/// A testing stub for the system's onscreen keyboard.
|
/// A testing stub for the system's onscreen keyboard.
|
||||||
///
|
///
|
||||||
/// Typical app tests will not need to use this class directly.
|
/// Typical app tests will not need to use this class directly.
|
||||||
///
|
///
|
||||||
|
/// The [TestWidgetsFlutterBinding] class registers a [TestTextInput] instance
|
||||||
|
/// ([TestWidgetsFlutterBinding.testTextInput]) as a stub keyboard
|
||||||
|
/// implementation if its [TestWidgetsFlutterBinding.registerTestTextInput]
|
||||||
|
/// property returns true when a test starts, and unregisters it when the test
|
||||||
|
/// ends (unless it ends with a failure).
|
||||||
|
///
|
||||||
|
/// See [register], [unregister], and [isRegistered] for details.
|
||||||
|
///
|
||||||
|
/// The [enterText], [updateEditingValue], [receiveAction], and
|
||||||
|
/// [closeConnection] methods can be used even when the [TestTextInput] is not
|
||||||
|
/// registered. All other methods will assert if [isRegistered] is false.
|
||||||
|
///
|
||||||
/// See also:
|
/// See also:
|
||||||
///
|
///
|
||||||
/// * [WidgetTester.enterText], which uses this class to simulate keyboard input.
|
/// * [WidgetTester.enterText], which uses this class to simulate keyboard input.
|
||||||
@ -33,61 +49,76 @@ class TestTextInput {
|
|||||||
/// first be requested, e.g. using [WidgetTester.showKeyboard].
|
/// first be requested, e.g. using [WidgetTester.showKeyboard].
|
||||||
final VoidCallback? onCleared;
|
final VoidCallback? onCleared;
|
||||||
|
|
||||||
/// The messenger which sends the bytes for this channel, not null.
|
|
||||||
BinaryMessenger get _binaryMessenger => ServicesBinding.instance!.defaultBinaryMessenger;
|
|
||||||
|
|
||||||
/// Resets any internal state of this object and calls [register].
|
|
||||||
///
|
|
||||||
/// This method is invoked by the testing framework between tests. It should
|
|
||||||
/// not ordinarily be called by tests directly.
|
|
||||||
void resetAndRegister() {
|
|
||||||
log.clear();
|
|
||||||
editingState = null;
|
|
||||||
setClientArgs = null;
|
|
||||||
_client = 0;
|
|
||||||
_isVisible = false;
|
|
||||||
register();
|
|
||||||
}
|
|
||||||
/// Installs this object as a mock handler for [SystemChannels.textInput].
|
|
||||||
void register() => SystemChannels.textInput.setMockMethodCallHandler(_handleTextInputCall);
|
|
||||||
|
|
||||||
/// Removes this object as a mock handler for [SystemChannels.textInput].
|
|
||||||
///
|
|
||||||
/// After calling this method, the channel will exchange messages with the
|
|
||||||
/// Flutter engine. Use this with [FlutterDriver] tests that need to display
|
|
||||||
/// on-screen keyboard provided by the operating system.
|
|
||||||
void unregister() => SystemChannels.textInput.setMockMethodCallHandler(null);
|
|
||||||
|
|
||||||
/// Log for method calls.
|
/// Log for method calls.
|
||||||
///
|
///
|
||||||
/// For all registered channels, handled calls are added to the list. Can
|
/// For all registered channels, handled calls are added to the list. Can
|
||||||
/// be cleaned using `log.clear()`.
|
/// be cleaned using `log.clear()`.
|
||||||
final List<MethodCall> log = <MethodCall>[];
|
final List<MethodCall> log = <MethodCall>[];
|
||||||
|
|
||||||
|
/// Installs this object as a mock handler for [SystemChannels.textInput].
|
||||||
|
///
|
||||||
|
/// Called by the binding at the top of a test when
|
||||||
|
/// [TestWidgetsFlutterBinding.registerTestTextInput] is true.
|
||||||
|
void register() => SystemChannels.textInput.setMockMethodCallHandler(_handleTextInputCall);
|
||||||
|
|
||||||
|
/// Removes this object as a mock handler for [SystemChannels.textInput].
|
||||||
|
///
|
||||||
|
/// After calling this method, the channel will exchange messages with the
|
||||||
|
/// Flutter engine instead of the stub.
|
||||||
|
///
|
||||||
|
/// Called by the binding at the end of a (successful) test when
|
||||||
|
/// [TestWidgetsFlutterBinding.registerTestTextInput] is true.
|
||||||
|
void unregister() => SystemChannels.textInput.setMockMethodCallHandler(null);
|
||||||
|
|
||||||
/// Whether this [TestTextInput] is registered with [SystemChannels.textInput].
|
/// Whether this [TestTextInput] is registered with [SystemChannels.textInput].
|
||||||
///
|
///
|
||||||
/// Use [register] and [unregister] methods to control this value.
|
/// The binding uses the [register] and [unregister] methods to control this
|
||||||
|
/// value when [TestWidgetsFlutterBinding.registerTestTextInput] is true.
|
||||||
bool get isRegistered => SystemChannels.textInput.checkMockMethodCallHandler(_handleTextInputCall);
|
bool get isRegistered => SystemChannels.textInput.checkMockMethodCallHandler(_handleTextInputCall);
|
||||||
|
|
||||||
|
int? _client;
|
||||||
|
|
||||||
/// Whether there are any active clients listening to text input.
|
/// Whether there are any active clients listening to text input.
|
||||||
bool get hasAnyClients {
|
bool get hasAnyClients {
|
||||||
assert(isRegistered);
|
assert(isRegistered);
|
||||||
return _client > 0;
|
return _client != null && _client! > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int _client = 0;
|
/// The last set of arguments supplied to the `TextInput.setClient` and
|
||||||
|
/// `TextInput.updateConfig` methods of this stub implementation.
|
||||||
/// Arguments supplied to the TextInput.setClient method call.
|
|
||||||
Map<String, dynamic>? setClientArgs;
|
Map<String, dynamic>? setClientArgs;
|
||||||
|
|
||||||
/// The last set of arguments that [TextInputConnection.setEditingState] sent
|
/// The last set of arguments that [TextInputConnection.setEditingState] sent
|
||||||
/// to the embedder.
|
/// to this stub implementation (i.e. the arguments set to
|
||||||
|
/// `TextInput.setEditingState`).
|
||||||
///
|
///
|
||||||
/// This is a map representation of a [TextEditingValue] object. For example,
|
/// This is a map representation of a [TextEditingValue] object. For example,
|
||||||
/// it will have a `text` entry whose value matches the most recent
|
/// it will have a `text` entry whose value matches the most recent
|
||||||
/// [TextEditingValue.text] that was sent to the embedder.
|
/// [TextEditingValue.text] that was sent to the embedder.
|
||||||
Map<String, dynamic>? editingState;
|
Map<String, dynamic>? editingState;
|
||||||
|
|
||||||
|
/// Whether the onscreen keyboard is visible to the user.
|
||||||
|
///
|
||||||
|
/// Specifically, this reflects the last call to `TextInput.show` or
|
||||||
|
/// `TextInput.hide` received by the stub implementation.
|
||||||
|
bool get isVisible {
|
||||||
|
assert(isRegistered);
|
||||||
|
return _isVisible;
|
||||||
|
}
|
||||||
|
bool _isVisible = false;
|
||||||
|
|
||||||
|
/// Resets any internal state of this object.
|
||||||
|
///
|
||||||
|
/// This method is invoked by the testing framework between tests. It should
|
||||||
|
/// not ordinarily be called by tests directly.
|
||||||
|
void reset() {
|
||||||
|
log.clear();
|
||||||
|
_client = null;
|
||||||
|
setClientArgs = null;
|
||||||
|
editingState = null;
|
||||||
|
_isVisible = false;
|
||||||
|
}
|
||||||
|
|
||||||
Future<dynamic> _handleTextInputCall(MethodCall methodCall) async {
|
Future<dynamic> _handleTextInputCall(MethodCall methodCall) async {
|
||||||
log.add(methodCall);
|
log.add(methodCall);
|
||||||
switch (methodCall.method) {
|
switch (methodCall.method) {
|
||||||
@ -99,7 +130,7 @@ class TestTextInput {
|
|||||||
setClientArgs = methodCall.arguments as Map<String, dynamic>;
|
setClientArgs = methodCall.arguments as Map<String, dynamic>;
|
||||||
break;
|
break;
|
||||||
case 'TextInput.clearClient':
|
case 'TextInput.clearClient':
|
||||||
_client = 0;
|
_client = null;
|
||||||
_isVisible = false;
|
_isVisible = false;
|
||||||
onCleared?.call();
|
onCleared?.call();
|
||||||
break;
|
break;
|
||||||
@ -115,87 +146,86 @@ class TestTextInput {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Whether the onscreen keyboard is visible to the user.
|
/// Simulates the user hiding the onscreen keyboard.
|
||||||
bool get isVisible {
|
|
||||||
assert(isRegistered);
|
|
||||||
return _isVisible;
|
|
||||||
}
|
|
||||||
bool _isVisible = false;
|
|
||||||
|
|
||||||
/// Simulates the user changing the [TextEditingValue] to the given value.
|
|
||||||
void updateEditingValue(TextEditingValue value) {
|
|
||||||
assert(isRegistered);
|
|
||||||
// Not using the `expect` function because in the case of a FlutterDriver
|
|
||||||
// test this code does not run in a package:test test zone.
|
|
||||||
if (_client == 0)
|
|
||||||
throw TestFailure('Tried to use TestTextInput with no keyboard attached. You must use WidgetTester.showKeyboard() first.');
|
|
||||||
_binaryMessenger.handlePlatformMessage(
|
|
||||||
SystemChannels.textInput.name,
|
|
||||||
SystemChannels.textInput.codec.encodeMethodCall(
|
|
||||||
MethodCall(
|
|
||||||
'TextInputClient.updateEditingState',
|
|
||||||
<dynamic>[_client, value.toJSON()],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
(ByteData? data) { /* response from framework is discarded */ },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Simulates the user closing the text input connection.
|
|
||||||
///
|
///
|
||||||
/// For example:
|
/// This does nothing but set the internal flag.
|
||||||
/// - User pressed the home button and sent the application to background.
|
void hide() {
|
||||||
/// - User closed the virtual keyboard.
|
|
||||||
void closeConnection() {
|
|
||||||
assert(isRegistered);
|
assert(isRegistered);
|
||||||
// Not using the `expect` function because in the case of a FlutterDriver
|
_isVisible = false;
|
||||||
// test this code does not run in a package:test test zone.
|
|
||||||
if (_client == 0)
|
|
||||||
throw TestFailure('Tried to use TestTextInput with no keyboard attached. You must use WidgetTester.showKeyboard() first.');
|
|
||||||
_binaryMessenger.handlePlatformMessage(
|
|
||||||
SystemChannels.textInput.name,
|
|
||||||
SystemChannels.textInput.codec.encodeMethodCall(
|
|
||||||
MethodCall(
|
|
||||||
'TextInputClient.onConnectionClosed',
|
|
||||||
<dynamic>[_client,]
|
|
||||||
),
|
|
||||||
),
|
|
||||||
(ByteData? data) { /* response from framework is discarded */ },
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Simulates the user typing the given text.
|
/// Simulates the user changing the text of the focused text field, and resets
|
||||||
|
/// the selection.
|
||||||
///
|
///
|
||||||
/// Calling this method replaces the content of the connected input field with
|
/// Calling this method replaces the content of the connected input field with
|
||||||
/// `text`, and places the caret at the end of the text.
|
/// `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) {
|
void enterText(String text) {
|
||||||
assert(isRegistered);
|
|
||||||
updateEditingValue(TextEditingValue(
|
updateEditingValue(TextEditingValue(
|
||||||
text: text,
|
text: text,
|
||||||
selection: TextSelection.collapsed(offset: text.length),
|
selection: TextSelection.collapsed(offset: text.length),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 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(
|
||||||
|
SystemChannels.textInput.name,
|
||||||
|
SystemChannels.textInput.codec.encodeMethodCall(
|
||||||
|
MethodCall(
|
||||||
|
'TextInputClient.updateEditingState',
|
||||||
|
<dynamic>[_client ?? -1, value.toJSON()],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(ByteData? data) { /* ignored */ },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/// Simulates the user pressing one of the [TextInputAction] buttons.
|
/// Simulates the user pressing one of the [TextInputAction] buttons.
|
||||||
/// Does not check that the [TextInputAction] performed is an acceptable one
|
/// Does not check that the [TextInputAction] performed is an acceptable one
|
||||||
/// based on the `inputAction` [setClientArgs].
|
/// based on the `inputAction` [setClientArgs].
|
||||||
|
///
|
||||||
|
/// This can be called even if the [TestTextInput] has not been [register]ed.
|
||||||
|
///
|
||||||
|
/// If this is used to inject an action when there is a real IME connection,
|
||||||
|
/// for example when using the [integration_test] library, there is a risk
|
||||||
|
/// that the real IME will become confused as to the current state of input.
|
||||||
Future<void> receiveAction(TextInputAction action) async {
|
Future<void> receiveAction(TextInputAction action) async {
|
||||||
assert(isRegistered);
|
|
||||||
return TestAsyncUtils.guard(() {
|
return TestAsyncUtils.guard(() {
|
||||||
// Not using the `expect` function because in the case of a FlutterDriver
|
|
||||||
// test this code does not run in a package:test test zone.
|
|
||||||
if (_client == 0) {
|
|
||||||
throw TestFailure('Tried to use TestTextInput with no keyboard attached. You must use WidgetTester.showKeyboard() first.');
|
|
||||||
}
|
|
||||||
|
|
||||||
final Completer<void> completer = Completer<void>();
|
final Completer<void> completer = Completer<void>();
|
||||||
|
TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.handlePlatformMessage(
|
||||||
_binaryMessenger.handlePlatformMessage(
|
|
||||||
SystemChannels.textInput.name,
|
SystemChannels.textInput.name,
|
||||||
SystemChannels.textInput.codec.encodeMethodCall(
|
SystemChannels.textInput.codec.encodeMethodCall(
|
||||||
MethodCall(
|
MethodCall(
|
||||||
'TextInputClient.performAction',
|
'TextInputClient.performAction',
|
||||||
<dynamic>[_client, action.toString()],
|
<dynamic>[_client ?? -1, action.toString()],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
(ByteData? data) {
|
(ByteData? data) {
|
||||||
@ -204,8 +234,7 @@ class TestTextInput {
|
|||||||
// Decoding throws a PlatformException if the data represents an
|
// Decoding throws a PlatformException if the data represents an
|
||||||
// error, and that's all we care about here.
|
// error, and that's all we care about here.
|
||||||
SystemChannels.textInput.codec.decodeEnvelope(data!);
|
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();
|
completer.complete();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// An exception occurred as a result of receiveAction()'ing. Report
|
// An exception occurred as a result of receiveAction()'ing. Report
|
||||||
@ -214,14 +243,32 @@ class TestTextInput {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
return completer.future;
|
return completer.future;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Simulates the user hiding the onscreen keyboard.
|
/// Simulates the user closing the text input connection.
|
||||||
void hide() {
|
///
|
||||||
assert(isRegistered);
|
/// For example:
|
||||||
_isVisible = false;
|
///
|
||||||
|
/// * User pressed the home button and sent the application to background.
|
||||||
|
/// * User closed the virtual keyboard.
|
||||||
|
///
|
||||||
|
/// This can be called even if the [TestTextInput] has not been [register]ed.
|
||||||
|
///
|
||||||
|
/// If this is used to inject text when there is a real IME connection, for
|
||||||
|
/// example when using the [integration_test] library, there is a risk that
|
||||||
|
/// the real IME will become confused as to the current state of input.
|
||||||
|
void closeConnection() {
|
||||||
|
TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.handlePlatformMessage(
|
||||||
|
SystemChannels.textInput.name,
|
||||||
|
SystemChannels.textInput.codec.encodeMethodCall(
|
||||||
|
MethodCall(
|
||||||
|
'TextInputClient.onConnectionClosed',
|
||||||
|
<dynamic>[_client ?? -1],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(ByteData? data) { /* response from framework is discarded */ },
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -129,7 +129,7 @@ void testWidgets(
|
|||||||
dynamic tags,
|
dynamic tags,
|
||||||
}) {
|
}) {
|
||||||
assert(variant != null);
|
assert(variant != null);
|
||||||
assert(variant.values.isNotEmpty, 'There must be at least on value to test in the testing variant');
|
assert(variant.values.isNotEmpty, 'There must be at least one value to test in the testing variant.');
|
||||||
final TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized() as TestWidgetsFlutterBinding;
|
final TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized() as TestWidgetsFlutterBinding;
|
||||||
final WidgetTester tester = WidgetTester._(binding);
|
final WidgetTester tester = WidgetTester._(binding);
|
||||||
for (final dynamic value in variant.values) {
|
for (final dynamic value in variant.values) {
|
||||||
@ -147,9 +147,8 @@ void testWidgets(
|
|||||||
test_package.addTearDown(binding.postTest);
|
test_package.addTearDown(binding.postTest);
|
||||||
return binding.runTest(
|
return binding.runTest(
|
||||||
() async {
|
() async {
|
||||||
binding.reset();
|
binding.reset(); // TODO(ianh): the binding should just do this itself in _runTest
|
||||||
debugResetSemanticsIdCounter();
|
debugResetSemanticsIdCounter();
|
||||||
tester.resetTestTextInput();
|
|
||||||
Object? memento;
|
Object? memento;
|
||||||
try {
|
try {
|
||||||
memento = await variant.setUp(value);
|
memento = await variant.setUp(value);
|
||||||
@ -918,10 +917,12 @@ class WidgetTester extends WidgetController implements HitTestDispatcher, Ticker
|
|||||||
/// Acts as if the application went idle.
|
/// Acts as if the application went idle.
|
||||||
///
|
///
|
||||||
/// Runs all remaining microtasks, including those scheduled as a result of
|
/// Runs all remaining microtasks, including those scheduled as a result of
|
||||||
/// running them, until there are no more microtasks scheduled.
|
/// running them, until there are no more microtasks scheduled. Then, runs any
|
||||||
|
/// previously scheduled timers with zero time, and completes the returned future.
|
||||||
///
|
///
|
||||||
/// Does not run timers. May result in an infinite loop or run out of memory
|
/// May result in an infinite loop or run out of memory if microtasks continue
|
||||||
/// if microtasks continue to recursively schedule new microtasks.
|
/// to recursively schedule new microtasks. Will not run any timers scheduled
|
||||||
|
/// after this method was invoked, even if they are zero-time timers.
|
||||||
Future<void> idle() {
|
Future<void> idle() {
|
||||||
return TestAsyncUtils.guard<void>(() => binding.idle());
|
return TestAsyncUtils.guard<void>(() => binding.idle());
|
||||||
}
|
}
|
||||||
@ -1002,18 +1003,13 @@ class WidgetTester extends WidgetController implements HitTestDispatcher, Ticker
|
|||||||
///
|
///
|
||||||
/// Typical app tests will not need to use this value. To add text to widgets
|
/// Typical app tests will not need to use this value. To add text to widgets
|
||||||
/// like [TextField] or [TextFormField], call [enterText].
|
/// like [TextField] or [TextFormField], call [enterText].
|
||||||
TestTextInput get testTextInput => binding.testTextInput;
|
|
||||||
|
|
||||||
/// Ensures that [testTextInput] is registered and [TestTextInput.log] is
|
|
||||||
/// reset.
|
|
||||||
///
|
///
|
||||||
/// This is called by the testing framework before test runs, so that if a
|
/// Some of the properties and methods on this value are only valid if the
|
||||||
/// previous test has set its own handler on [SystemChannels.textInput], the
|
/// binding's [TestWidgetsFlutterBinding.registerTestTextInput] flag is set to
|
||||||
/// [testTextInput] regains control and the log is fresh for the new test.
|
/// true as a test is starting (meaning that the keyboard is to be simulated
|
||||||
/// It should not typically need to be called by tests.
|
/// by the test framework). If those members are accessed when using a binding
|
||||||
void resetTestTextInput() {
|
/// that sets this flag to false, they will throw.
|
||||||
testTextInput.resetAndRegister();
|
TestTextInput get testTextInput => binding.testTextInput;
|
||||||
}
|
|
||||||
|
|
||||||
/// Give the text input widget specified by [finder] the focus, as if the
|
/// Give the text input widget specified by [finder] the focus, as if the
|
||||||
/// onscreen keyboard had appeared.
|
/// onscreen keyboard had appeared.
|
||||||
@ -1035,6 +1031,9 @@ class WidgetTester extends WidgetController implements HitTestDispatcher, Ticker
|
|||||||
matchRoot: true,
|
matchRoot: true,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
// Setting focusedEditable causes the binding to call requestKeyboard()
|
||||||
|
// on the EditableTextState, which itself eventually calls TextInput.attach
|
||||||
|
// to establish the connection.
|
||||||
binding.focusedEditable = editable;
|
binding.focusedEditable = editable;
|
||||||
await pump();
|
await pump();
|
||||||
});
|
});
|
||||||
@ -1052,6 +1051,12 @@ class WidgetTester extends WidgetController implements HitTestDispatcher, Ticker
|
|||||||
///
|
///
|
||||||
/// To just give [finder] the focus without entering any text,
|
/// To just give [finder] the focus without entering any text,
|
||||||
/// see [showKeyboard].
|
/// see [showKeyboard].
|
||||||
|
///
|
||||||
|
/// To enter text into other widgets (e.g. a custom widget that maintains a
|
||||||
|
/// TextInputConnection the way that a [EditableText] does), first ensure that
|
||||||
|
/// that widget has an open connection (e.g. by using [tap] to to focus it),
|
||||||
|
/// then call `testTextInput.enterText` directly (see
|
||||||
|
/// [TestTextInput.enterText]).
|
||||||
Future<void> enterText(Finder finder, String text) async {
|
Future<void> enterText(Finder finder, String text) async {
|
||||||
return TestAsyncUtils.guard<void>(() async {
|
return TestAsyncUtils.guard<void>(() async {
|
||||||
await showKeyboard(finder);
|
await showKeyboard(finder);
|
||||||
|
@ -379,8 +379,16 @@ class TestWindow implements ui.SingletonFlutterWindow {
|
|||||||
platformDispatcher.sendPlatformMessage(name, data, callback);
|
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
|
@override
|
||||||
ui.PlatformMessageCallback? get onPlatformMessage => platformDispatcher.onPlatformMessage;
|
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
|
@override
|
||||||
set onPlatformMessage(ui.PlatformMessageCallback? callback) {
|
set onPlatformMessage(ui.PlatformMessageCallback? callback) {
|
||||||
platformDispatcher.onPlatformMessage = callback;
|
platformDispatcher.onPlatformMessage = callback;
|
||||||
|
@ -11,6 +11,8 @@ import 'package:flutter_test/flutter_test.dart';
|
|||||||
import 'package:test_api/test_api.dart' as test_package;
|
import 'package:test_api/test_api.dart' as test_package;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
final AutomatedTestWidgetsFlutterBinding binding = AutomatedTestWidgetsFlutterBinding();
|
||||||
|
|
||||||
group(TestViewConfiguration, () {
|
group(TestViewConfiguration, () {
|
||||||
test('is initialized with top-level window if one is not provided', () {
|
test('is initialized with top-level window if one is not provided', () {
|
||||||
// The code below will throw without the default.
|
// The code below will throw without the default.
|
||||||
@ -20,15 +22,32 @@ void main() {
|
|||||||
|
|
||||||
group(AutomatedTestWidgetsFlutterBinding, () {
|
group(AutomatedTestWidgetsFlutterBinding, () {
|
||||||
test('allows setting defaultTestTimeout to 5 minutes', () {
|
test('allows setting defaultTestTimeout to 5 minutes', () {
|
||||||
final AutomatedTestWidgetsFlutterBinding binding = AutomatedTestWidgetsFlutterBinding();
|
|
||||||
binding.defaultTestTimeout = const test_package.Timeout(Duration(minutes: 5));
|
binding.defaultTestTimeout = const test_package.Timeout(Duration(minutes: 5));
|
||||||
expect(binding.defaultTestTimeout.duration, const Duration(minutes: 5));
|
expect(binding.defaultTestTimeout.duration, const Duration(minutes: 5));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// The next three tests must run in order -- first using `test`, then `testWidgets`, then `test` again.
|
||||||
|
|
||||||
|
int order = 0;
|
||||||
|
|
||||||
test('Initializes httpOverrides and testTextInput', () async {
|
test('Initializes httpOverrides and testTextInput', () async {
|
||||||
final TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized() as TestWidgetsFlutterBinding;
|
assert(order == 0);
|
||||||
expect(binding.testTextInput.isRegistered, true);
|
expect(binding.testTextInput, isNotNull);
|
||||||
|
expect(binding.testTextInput.isRegistered, isFalse);
|
||||||
expect(HttpOverrides.current, isNotNull);
|
expect(HttpOverrides.current, isNotNull);
|
||||||
|
order += 1;
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('Registers testTextInput', (WidgetTester tester) async {
|
||||||
|
assert(order == 1);
|
||||||
|
expect(tester.testTextInput.isRegistered, isTrue);
|
||||||
|
order += 1;
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Unregisters testTextInput', () async {
|
||||||
|
assert(order == 2);
|
||||||
|
expect(binding.testTextInput.isRegistered, isFalse);
|
||||||
|
order += 1;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -20,12 +20,6 @@ class TestDelegate extends BinaryMessenger {
|
|||||||
Future<void> handlePlatformMessage(String channel, ByteData? data, ui.PlatformMessageResponseCallback? callback) => throw UnimplementedError();
|
Future<void> handlePlatformMessage(String channel, ByteData? data, ui.PlatformMessageResponseCallback? callback) => throw UnimplementedError();
|
||||||
@override
|
@override
|
||||||
void setMessageHandler(String channel, MessageHandler? handler) => throw UnimplementedError();
|
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() {
|
void main() {
|
||||||
|
@ -61,7 +61,7 @@ class Registrar extends BinaryMessenger {
|
|||||||
/// the [dart:ui] library. That function is only available when
|
/// the [dart:ui] library. That function is only available when
|
||||||
/// compiling for the web.
|
/// compiling for the web.
|
||||||
void registerMessageHandler() {
|
void registerMessageHandler() {
|
||||||
// The function below is only defined in the Web dart:ui.
|
// The `ui.webOnlySetPluginHandler` function below is only defined in the Web dart:ui.
|
||||||
// ignore: undefined_function
|
// ignore: undefined_function
|
||||||
ui.webOnlySetPluginHandler(handleFrameworkMessage);
|
ui.webOnlySetPluginHandler(handleFrameworkMessage);
|
||||||
}
|
}
|
||||||
@ -141,7 +141,7 @@ class Registrar extends BinaryMessenger {
|
|||||||
@override
|
@override
|
||||||
Future<ByteData?> send(String channel, ByteData? message) {
|
Future<ByteData?> send(String channel, ByteData? message) {
|
||||||
final Completer<ByteData?> completer = Completer<ByteData?>();
|
final Completer<ByteData?> completer = Completer<ByteData?>();
|
||||||
ui.window.onPlatformMessage!(channel, message, (ByteData? reply) {
|
ui.channelBuffers.push(channel, message, (ByteData? reply) {
|
||||||
try {
|
try {
|
||||||
completer.complete(reply);
|
completer.complete(reply);
|
||||||
} catch (exception, stack) {
|
} catch (exception, stack) {
|
||||||
@ -163,26 +163,6 @@ class Registrar extends BinaryMessenger {
|
|||||||
else
|
else
|
||||||
_handlers[channel] = handler;
|
_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
|
/// This class was previously separate from [Registrar] but was merged into it
|
||||||
|
@ -71,12 +71,5 @@ void main() {
|
|||||||
ServicesBinding.instance!.defaultBinaryMessenger
|
ServicesBinding.instance!.defaultBinaryMessenger
|
||||||
.setMessageHandler('test_send', null);
|
.setMessageHandler('test_send', null);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('throws when trying to set a mock handler', () {
|
|
||||||
expect(
|
|
||||||
() => pluginBinaryMessenger.setMockMessageHandler(
|
|
||||||
'test', (ByteData? data) async => ByteData(0)),
|
|
||||||
throwsFlutterError);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user