Convert services tests to NNBD (#62694)
This converts the packages/flutter/test/services directory to NNBD, now that the services package is converted. I changed the signature of checkMessageHandler and checkMockMessageHandler on BinaryMessenger to take a nullable handler, since the tests wanted to check to make sure a handler wasn't set, and that functionality no longer works if the handler is non-nullable.
This commit is contained in:
parent
ddab09f553
commit
58287aceef
@ -3,6 +3,8 @@
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the LICENSE file.
|
||||
|
||||
set -e
|
||||
|
||||
# The tests to run on Firebase Test Lab.
|
||||
# Currently, the test consists on building an Android App Bundle and ensuring
|
||||
# that the app doesn't crash upon startup.
|
||||
@ -26,8 +28,6 @@ devices=(
|
||||
"model=griffin,version=24"
|
||||
)
|
||||
|
||||
set -e
|
||||
|
||||
GIT_REVISION=$(git rev-parse HEAD)
|
||||
|
||||
DEVICE_FLAG=""
|
||||
@ -35,6 +35,12 @@ for device in ${devices[*]}; do
|
||||
DEVICE_FLAG+="--device $device "
|
||||
done
|
||||
|
||||
# If running tests locally, the key env var needs to be set.
|
||||
if [[ -z $GCLOUD_FIREBASE_TESTLAB_KEY ]]; then
|
||||
echo "Not running firebase test lab tests because GCLOUD_FIREBASE_TESTLAB_KEY isn't set."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# New contributors will not have permissions to run this test - they won't be
|
||||
# able to access the service account information. We should just mark the test
|
||||
# as passed - it will run fine on post submit, where it will still catch
|
||||
|
@ -48,6 +48,9 @@ abstract class BinaryMessenger {
|
||||
///
|
||||
/// 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
|
||||
@ -69,6 +72,9 @@ abstract class BinaryMessenger {
|
||||
/// 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);
|
||||
}
|
||||
|
||||
|
@ -389,6 +389,9 @@ class MethodChannel {
|
||||
///
|
||||
/// 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.
|
||||
@ -422,6 +425,9 @@ class MethodChannel {
|
||||
///
|
||||
/// 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> handler(MethodCall call)) async {
|
||||
|
@ -2,8 +2,6 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'dart:convert';
|
||||
import 'dart:typed_data';
|
||||
|
||||
@ -41,7 +39,7 @@ void main() {
|
||||
|
||||
expect(bundle.loadCallCount['one'], 1);
|
||||
|
||||
Object loadException;
|
||||
late Object loadException;
|
||||
try {
|
||||
await bundle.loadString('foo');
|
||||
} catch (e) {
|
||||
@ -61,7 +59,7 @@ void main() {
|
||||
test('NetworkAssetBundle control test', () async {
|
||||
final Uri uri = Uri.http('example.org', '/path');
|
||||
final NetworkAssetBundle bundle = NetworkAssetBundle(uri);
|
||||
FlutterError error;
|
||||
late FlutterError error;
|
||||
try {
|
||||
await bundle.load('key');
|
||||
} on FlutterError catch (e) {
|
||||
|
@ -2,8 +2,6 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'dart:convert' show utf8;
|
||||
|
||||
import 'package:flutter/services.dart';
|
||||
@ -13,13 +11,12 @@ void main() {
|
||||
TestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
group('TextInput message channels', () {
|
||||
FakeTextChannel fakeTextChannel;
|
||||
FakeAutofillScope scope;
|
||||
late FakeTextChannel fakeTextChannel;
|
||||
final FakeAutofillScope scope = FakeAutofillScope();
|
||||
|
||||
setUp(() {
|
||||
fakeTextChannel = FakeTextChannel((MethodCall call) async {});
|
||||
TextInput.setChannel(fakeTextChannel);
|
||||
scope ??= FakeAutofillScope();
|
||||
scope.clients.clear();
|
||||
});
|
||||
|
||||
@ -28,35 +25,8 @@ void main() {
|
||||
TextInput.setChannel(SystemChannels.textInput);
|
||||
});
|
||||
|
||||
test('mandatory fields are mandatory', () async {
|
||||
AutofillConfiguration config;
|
||||
try {
|
||||
config = AutofillConfiguration(
|
||||
uniqueIdentifier: null,
|
||||
autofillHints: const <String>['test'],
|
||||
currentEditingValue: const TextEditingValue(),
|
||||
);
|
||||
} catch (e) {
|
||||
expect(e.toString(), contains('uniqueIdentifier != null'));
|
||||
}
|
||||
|
||||
expect(config, isNull);
|
||||
|
||||
try {
|
||||
config = AutofillConfiguration(
|
||||
uniqueIdentifier: 'id',
|
||||
autofillHints: null,
|
||||
currentEditingValue: const TextEditingValue(),
|
||||
);
|
||||
} catch (e) {
|
||||
expect(e.toString(), contains('autofillHints != null'));
|
||||
}
|
||||
|
||||
expect(config, isNull);
|
||||
});
|
||||
|
||||
test('throws if the hint list is empty', () async {
|
||||
Map<String, dynamic> json;
|
||||
Map<String, dynamic>? json;
|
||||
try {
|
||||
const AutofillConfiguration config = AutofillConfiguration(
|
||||
uniqueIdentifier: 'id',
|
||||
@ -113,7 +83,7 @@ void main() {
|
||||
]);
|
||||
|
||||
const TextEditingValue text2 = TextEditingValue(text: 'Text 2');
|
||||
fakeTextChannel.incoming(MethodCall(
|
||||
fakeTextChannel.incoming?.call(MethodCall(
|
||||
'TextInputClient.updateEditingStateWithTag',
|
||||
<dynamic>[0, <String, dynamic>{ client2.autofillId : text2.toJSON() }],
|
||||
));
|
||||
@ -130,7 +100,7 @@ class FakeAutofillClient implements TextInputClient, AutofillClient {
|
||||
String get autofillId => hashCode.toString();
|
||||
|
||||
@override
|
||||
TextInputConfiguration textInputConfiguration;
|
||||
late TextInputConfiguration textInputConfiguration;
|
||||
|
||||
@override
|
||||
void updateEditingValue(TextEditingValue newEditingValue) {
|
||||
@ -139,7 +109,7 @@ class FakeAutofillClient implements TextInputClient, AutofillClient {
|
||||
}
|
||||
|
||||
@override
|
||||
AutofillScope currentAutofillScope;
|
||||
AutofillScope? currentAutofillScope;
|
||||
|
||||
String latestMethodCall = '';
|
||||
|
||||
@ -179,7 +149,7 @@ class FakeAutofillScope with AutofillScopeMixin implements AutofillScope {
|
||||
Iterable<AutofillClient> get autofillClients => clients.values;
|
||||
|
||||
@override
|
||||
AutofillClient getAutofillClient(String autofillId) => clients[autofillId];
|
||||
AutofillClient getAutofillClient(String autofillId) => clients[autofillId]!;
|
||||
|
||||
void register(AutofillClient client) {
|
||||
clients.putIfAbsent(client.autofillId, () => client);
|
||||
@ -190,7 +160,7 @@ class FakeTextChannel implements MethodChannel {
|
||||
FakeTextChannel(this.outgoing) : assert(outgoing != null);
|
||||
|
||||
Future<dynamic> Function(MethodCall) outgoing;
|
||||
Future<void> Function(MethodCall) incoming;
|
||||
Future<void> Function(MethodCall)? incoming;
|
||||
|
||||
List<MethodCall> outgoingCalls = <MethodCall>[];
|
||||
|
||||
@ -217,18 +187,18 @@ class FakeTextChannel implements MethodChannel {
|
||||
String get name => 'flutter/textinput';
|
||||
|
||||
@override
|
||||
void setMethodCallHandler(Future<void> Function(MethodCall call) handler) {
|
||||
void setMethodCallHandler(Future<void> Function(MethodCall call)? handler) {
|
||||
incoming = handler;
|
||||
}
|
||||
|
||||
@override
|
||||
bool checkMethodCallHandler(Future<void> Function(MethodCall call) handler) => throw UnimplementedError();
|
||||
bool checkMethodCallHandler(Future<void> Function(MethodCall call)? handler) => throw UnimplementedError();
|
||||
|
||||
@override
|
||||
void setMockMethodCallHandler(Future<void> Function(MethodCall call) handler) => throw UnimplementedError();
|
||||
void setMockMethodCallHandler(Future<void> Function(MethodCall call)? handler) => throw UnimplementedError();
|
||||
|
||||
@override
|
||||
bool checkMockMethodCallHandler(Future<void> Function(MethodCall call) handler) => throw UnimplementedError();
|
||||
bool checkMockMethodCallHandler(Future<void> Function(MethodCall call)? handler) => throw UnimplementedError();
|
||||
|
||||
void validateOutgoingMethodCalls(List<MethodCall> calls) {
|
||||
expect(outgoingCalls.length, calls.length);
|
||||
|
@ -2,8 +2,6 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
@ -45,7 +43,7 @@ class TestBinding extends BindingBase with SchedulerBinding, ServicesBinding {
|
||||
@override
|
||||
BinaryMessenger createBinaryMessenger() {
|
||||
return super.createBinaryMessenger()
|
||||
..setMockMessageHandler('flutter/assets', (ByteData message) async {
|
||||
..setMockMessageHandler('flutter/assets', (ByteData? message) async {
|
||||
if (const StringCodec().decodeMessage(message) == 'NOTICES') {
|
||||
return const StringCodec().encodeMessage(licenses);
|
||||
}
|
||||
|
@ -2,8 +2,6 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
// TODO(yjbanov): enable Web when https://github.com/flutter/engine/pull/12747 rolls into the framework.
|
||||
@TestOn('!chrome')
|
||||
|
||||
@ -35,15 +33,15 @@ void main() {
|
||||
final TestChannelBuffersFlutterBinding binding = TestChannelBuffersFlutterBinding();
|
||||
expect(binding.defaultBinaryMessenger, isNotNull);
|
||||
bool didCallCallback = false;
|
||||
final ui.PlatformMessageResponseCallback callback = (ByteData responseData) {
|
||||
final ui.PlatformMessageResponseCallback callback = (ByteData? responseData) {
|
||||
didCallCallback = true;
|
||||
};
|
||||
const String payload = 'bar';
|
||||
final ByteData data = _makeByteData(payload);
|
||||
ui.channelBuffers.push(channel, data, callback);
|
||||
bool didDrainData = false;
|
||||
binding.defaultBinaryMessenger.setMessageHandler(channel, (ByteData message) async {
|
||||
expect(_getString(message), payload);
|
||||
binding.defaultBinaryMessenger.setMessageHandler(channel, (ByteData? message) async {
|
||||
expect(_getString(message!), payload);
|
||||
didDrainData = true;
|
||||
return null;
|
||||
});
|
||||
|
@ -2,8 +2,6 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'dart:convert';
|
||||
import 'dart:typed_data';
|
||||
import 'dart:ui' as ui;
|
||||
@ -23,22 +21,21 @@ void main() {
|
||||
test('default binary messenger calls callback once', () async {
|
||||
int count = 0;
|
||||
const String channel = 'foo';
|
||||
ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage(
|
||||
channel, _makeByteData('bar'), (ByteData message) async {
|
||||
ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage(
|
||||
channel, _makeByteData('bar'), (ByteData? message) async {
|
||||
count += 1;
|
||||
});
|
||||
expect(count, equals(0));
|
||||
await ui.channelBuffers.drain(channel,
|
||||
(ByteData data, ui.PlatformMessageResponseCallback callback) {
|
||||
(ByteData? data, ui.PlatformMessageResponseCallback callback) async {
|
||||
callback(null);
|
||||
return null;
|
||||
});
|
||||
expect(count, equals(1));
|
||||
});
|
||||
|
||||
test('can check the handler', () {
|
||||
Future<ByteData> handler(ByteData call) => Future<ByteData>.value(null);
|
||||
final BinaryMessenger messenger = ServicesBinding.instance.defaultBinaryMessenger;
|
||||
Future<ByteData> handler(ByteData? call) => Future<ByteData>.value(null);
|
||||
final BinaryMessenger messenger = ServicesBinding.instance!.defaultBinaryMessenger;
|
||||
|
||||
expect(messenger.checkMessageHandler('test_channel', null), true);
|
||||
expect(messenger.checkMessageHandler('test_channel', handler), false);
|
||||
@ -48,8 +45,8 @@ void main() {
|
||||
});
|
||||
|
||||
test('can check the mock handler', () {
|
||||
Future<ByteData> handler(ByteData call) => Future<ByteData>.value(null);
|
||||
final BinaryMessenger messenger = ServicesBinding.instance.defaultBinaryMessenger;
|
||||
Future<ByteData> handler(ByteData? call) => Future<ByteData>.value(null);
|
||||
final BinaryMessenger messenger = ServicesBinding.instance!.defaultBinaryMessenger;
|
||||
|
||||
expect(messenger.checkMockMessageHandler('test_channel', null), true);
|
||||
expect(messenger.checkMockMessageHandler('test_channel', handler), false);
|
||||
|
@ -2,8 +2,6 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:typed_data';
|
||||
|
||||
@ -14,10 +12,7 @@ import 'package:flutter/widgets.dart';
|
||||
|
||||
/// Used in internal testing.
|
||||
class FakePlatformViewController extends PlatformViewController {
|
||||
|
||||
FakePlatformViewController(int id) {
|
||||
_id = id;
|
||||
}
|
||||
FakePlatformViewController(this.viewId);
|
||||
|
||||
bool disposed = false;
|
||||
bool focusCleared = false;
|
||||
@ -25,10 +20,8 @@ class FakePlatformViewController extends PlatformViewController {
|
||||
/// Events that are dispatched.
|
||||
List<PointerEvent> dispatchedPointerEvents = <PointerEvent>[];
|
||||
|
||||
int _id;
|
||||
|
||||
@override
|
||||
int get viewId => _id;
|
||||
final int viewId;
|
||||
|
||||
@override
|
||||
Future<void> dispatchPointerEvent(PointerEvent event) async {
|
||||
@ -66,7 +59,7 @@ class FakeAndroidViewController implements AndroidViewController {
|
||||
final int viewId;
|
||||
|
||||
@override
|
||||
Offset Function(Offset position) pointTransformer;
|
||||
Offset Function(Offset position)? pointTransformer;
|
||||
|
||||
@override
|
||||
Future<void> dispatchPointerEvent(PointerEvent event) async {
|
||||
@ -98,7 +91,7 @@ class FakeAndroidViewController implements AndroidViewController {
|
||||
int get textureId => throw UnimplementedError();
|
||||
|
||||
@override
|
||||
bool isCreated;
|
||||
bool get isCreated => throw UnimplementedError();
|
||||
|
||||
@override
|
||||
void addOnPlatformViewCreatedListener(PlatformViewCreatedCallback listener) =>
|
||||
@ -133,7 +126,6 @@ class FakeAndroidPlatformViewsController {
|
||||
SystemChannels.platform_views.setMockMethodCallHandler(_onMethodCall);
|
||||
}
|
||||
|
||||
|
||||
Iterable<FakeAndroidPlatformView> get views => _views.values;
|
||||
final Map<int, FakeAndroidPlatformView> _views = <int, FakeAndroidPlatformView>{};
|
||||
|
||||
@ -143,11 +135,11 @@ class FakeAndroidPlatformViewsController {
|
||||
|
||||
int _textureCounter = 0;
|
||||
|
||||
Completer<void> resizeCompleter;
|
||||
Completer<void>? resizeCompleter;
|
||||
|
||||
Completer<void> createCompleter;
|
||||
Completer<void>? createCompleter;
|
||||
|
||||
int lastClearedFocusViewId;
|
||||
int? lastClearedFocusViewId;
|
||||
|
||||
void registerViewType(String viewType) {
|
||||
_registeredViewTypes.add(viewType);
|
||||
@ -156,7 +148,8 @@ class FakeAndroidPlatformViewsController {
|
||||
void invokeViewFocused(int viewId) {
|
||||
final MethodCodec codec = SystemChannels.platform_views.codec;
|
||||
final ByteData data = codec.encodeMethodCall(MethodCall('viewFocused', viewId));
|
||||
ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage(SystemChannels.platform_views.name, data, (ByteData data) {});
|
||||
ServicesBinding.instance!.defaultBinaryMessenger
|
||||
.handlePlatformMessage(SystemChannels.platform_views.name, data, (ByteData? data) {});
|
||||
}
|
||||
|
||||
Future<dynamic> _onMethodCall(MethodCall call) {
|
||||
@ -200,7 +193,7 @@ class FakeAndroidPlatformViewsController {
|
||||
);
|
||||
|
||||
if (createCompleter != null) {
|
||||
await createCompleter.future;
|
||||
await createCompleter!.future;
|
||||
}
|
||||
|
||||
_views[id] = FakeAndroidPlatformView(id, viewType,
|
||||
@ -219,9 +212,9 @@ class FakeAndroidPlatformViewsController {
|
||||
final int id = call.arguments['id'] as int;
|
||||
final bool hybrid = call.arguments['hybrid'] as bool;
|
||||
|
||||
if (hybrid && !_views[id].hybrid) {
|
||||
if (hybrid && !_views[id]!.hybrid!) {
|
||||
throw ArgumentError('An $AndroidViewController using hybrid composition must pass `hybrid: true`');
|
||||
} else if (!hybrid && _views[id].hybrid != null && _views[id].hybrid) {
|
||||
} else if (!hybrid && (_views[id]!.hybrid ?? false)) {
|
||||
throw ArgumentError('An $AndroidViewController not using hybrid composition must pass `hybrid: false`');
|
||||
}
|
||||
|
||||
@ -248,9 +241,9 @@ class FakeAndroidPlatformViewsController {
|
||||
);
|
||||
|
||||
if (resizeCompleter != null) {
|
||||
await resizeCompleter.future;
|
||||
await resizeCompleter!.future;
|
||||
}
|
||||
_views[id] = _views[id].copyWith(size: Size(width, height));
|
||||
_views[id] = _views[id]!.copyWith(size: Size(width, height));
|
||||
|
||||
return Future<dynamic>.sync(() => null);
|
||||
}
|
||||
@ -273,7 +266,7 @@ class FakeAndroidPlatformViewsController {
|
||||
if (!motionEvents.containsKey(id))
|
||||
motionEvents[id] = <FakeAndroidMotionEvent> [];
|
||||
|
||||
motionEvents[id].add(FakeAndroidMotionEvent(action, pointerIds, pointerOffsets));
|
||||
motionEvents[id]!.add(FakeAndroidMotionEvent(action, pointerIds, pointerOffsets));
|
||||
return Future<dynamic>.sync(() => null);
|
||||
}
|
||||
|
||||
@ -288,7 +281,7 @@ class FakeAndroidPlatformViewsController {
|
||||
message: 'Trying to resize a platform view with unknown id: $id',
|
||||
);
|
||||
|
||||
_views[id] = _views[id].copyWith(layoutDirection: layoutDirection);
|
||||
_views[id] = _views[id]!.copyWith(layoutDirection: layoutDirection);
|
||||
|
||||
return Future<dynamic>.sync(() => null);
|
||||
}
|
||||
@ -312,7 +305,6 @@ class FakeIosPlatformViewsController {
|
||||
SystemChannels.platform_views.setMockMethodCallHandler(_onMethodCall);
|
||||
}
|
||||
|
||||
|
||||
Iterable<FakeUiKitView> get views => _views.values;
|
||||
final Map<int, FakeUiKitView> _views = <int, FakeUiKitView>{};
|
||||
|
||||
@ -320,7 +312,7 @@ class FakeIosPlatformViewsController {
|
||||
|
||||
// When this completer is non null, the 'create' method channel call will be
|
||||
// delayed until it completes.
|
||||
Completer<void> creationDelay;
|
||||
Completer<void>? creationDelay;
|
||||
|
||||
// Maps a view id to the number of gestures it accepted so far.
|
||||
final Map<int, int> gesturesAccepted = <int, int>{};
|
||||
@ -348,7 +340,7 @@ class FakeIosPlatformViewsController {
|
||||
|
||||
Future<dynamic> _create(MethodCall call) async {
|
||||
if (creationDelay != null)
|
||||
await creationDelay.future;
|
||||
await creationDelay!.future;
|
||||
final Map<dynamic, dynamic> args = call.arguments as Map<dynamic, dynamic>;
|
||||
final int id = args['id'] as int;
|
||||
final String viewType = args['viewType'] as String;
|
||||
@ -371,21 +363,21 @@ class FakeIosPlatformViewsController {
|
||||
_views[id] = FakeUiKitView(id, viewType, creationParams);
|
||||
gesturesAccepted[id] = 0;
|
||||
gesturesRejected[id] = 0;
|
||||
return Future<int>.sync(() => null);
|
||||
return Future<int?>.sync(() => null);
|
||||
}
|
||||
|
||||
Future<dynamic> _acceptGesture(MethodCall call) async {
|
||||
final Map<dynamic, dynamic> args = call.arguments as Map<dynamic, dynamic>;
|
||||
final int id = args['id'] as int;
|
||||
gesturesAccepted[id] += 1;
|
||||
return Future<int>.sync(() => null);
|
||||
gesturesAccepted[id] = gesturesAccepted[id]! + 1;
|
||||
return Future<int?>.sync(() => null);
|
||||
}
|
||||
|
||||
Future<dynamic> _rejectGesture(MethodCall call) async {
|
||||
final Map<dynamic, dynamic> args = call.arguments as Map<dynamic, dynamic>;
|
||||
final int id = args['id'] as int;
|
||||
gesturesRejected[id] += 1;
|
||||
return Future<int>.sync(() => null);
|
||||
gesturesRejected[id] = gesturesRejected[id]! + 1;
|
||||
return Future<int?>.sync(() => null);
|
||||
}
|
||||
|
||||
Future<dynamic> _dispose(MethodCall call) {
|
||||
@ -413,9 +405,9 @@ class FakeHtmlPlatformViewsController {
|
||||
|
||||
final Set<String> _registeredViewTypes = <String>{};
|
||||
|
||||
Completer<void> resizeCompleter;
|
||||
late Completer<void> resizeCompleter;
|
||||
|
||||
Completer<void> createCompleter;
|
||||
Completer<void>? createCompleter;
|
||||
|
||||
void registerViewType(String viewType) {
|
||||
_registeredViewTypes.add(viewType);
|
||||
@ -449,11 +441,11 @@ class FakeHtmlPlatformViewsController {
|
||||
);
|
||||
|
||||
if (createCompleter != null) {
|
||||
await createCompleter.future;
|
||||
await createCompleter!.future;
|
||||
}
|
||||
|
||||
_views[id] = FakeHtmlPlatformView(id, viewType);
|
||||
return Future<int>.sync(() => null);
|
||||
return Future<int?>.sync(() => null);
|
||||
}
|
||||
|
||||
Future<dynamic> _dispose(MethodCall call) {
|
||||
@ -476,12 +468,12 @@ class FakeAndroidPlatformView {
|
||||
|
||||
final int id;
|
||||
final String type;
|
||||
final Uint8List creationParams;
|
||||
final Size size;
|
||||
final Uint8List? creationParams;
|
||||
final Size? size;
|
||||
final int layoutDirection;
|
||||
final bool hybrid;
|
||||
final bool? hybrid;
|
||||
|
||||
FakeAndroidPlatformView copyWith({Size size, int layoutDirection}) => FakeAndroidPlatformView(
|
||||
FakeAndroidPlatformView copyWith({Size? size, int? layoutDirection}) => FakeAndroidPlatformView(
|
||||
id,
|
||||
type,
|
||||
size ?? this.size,
|
||||
@ -544,7 +536,7 @@ class FakeUiKitView {
|
||||
|
||||
final int id;
|
||||
final String type;
|
||||
final Uint8List creationParams;
|
||||
final Uint8List? creationParams;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
|
@ -2,8 +2,6 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:flutter/services.dart';
|
||||
|
@ -2,8 +2,6 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
|
@ -2,8 +2,6 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
|
@ -2,8 +2,6 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
@ -11,7 +9,7 @@ void main() {
|
||||
testWidgets('initialLifecycleState is used to init state paused', (WidgetTester tester) async {
|
||||
// The lifecycleState is null initially in tests as there is no
|
||||
// initialLifecycleState.
|
||||
expect(ServicesBinding.instance.lifecycleState, equals(null));
|
||||
expect(ServicesBinding.instance!.lifecycleState, equals(null));
|
||||
// Mock the Window to provide paused as the AppLifecycleState
|
||||
final TestWidgetsFlutterBinding binding = tester.binding;
|
||||
// Use paused as the initial state.
|
||||
@ -20,6 +18,6 @@ void main() {
|
||||
|
||||
// The lifecycleState should now be the state we passed above,
|
||||
// even though no lifecycle event was fired from the platform.
|
||||
expect(ServicesBinding.instance.lifecycleState.toString(), equals('AppLifecycleState.paused'));
|
||||
expect(ServicesBinding.instance!.lifecycleState.toString(), equals('AppLifecycleState.paused'));
|
||||
});
|
||||
}
|
||||
|
@ -2,8 +2,6 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
// This files contains message codec tests that are supported both on the Web
|
||||
// and in the VM. For VM-only tests see message_codecs_vm_test.dart.
|
||||
|
||||
@ -18,26 +16,25 @@ import 'message_codecs_testing.dart';
|
||||
|
||||
void main() {
|
||||
group('Binary codec', () {
|
||||
const MessageCodec<ByteData> binary = BinaryCodec();
|
||||
const MessageCodec<ByteData?> binary = BinaryCodec();
|
||||
test('should encode and decode simple messages', () {
|
||||
checkEncodeDecode<ByteData>(binary, null);
|
||||
checkEncodeDecode<ByteData>(binary, ByteData(0));
|
||||
checkEncodeDecode<ByteData>(binary, ByteData(4)..setInt32(0, -7));
|
||||
checkEncodeDecode<ByteData?>(binary, null);
|
||||
checkEncodeDecode<ByteData?>(binary, ByteData(0));
|
||||
checkEncodeDecode<ByteData?>(binary, ByteData(4)..setInt32(0, -7));
|
||||
});
|
||||
});
|
||||
group('String codec', () {
|
||||
const MessageCodec<String> string = StringCodec();
|
||||
const MessageCodec<String?> string = StringCodec();
|
||||
test('should encode and decode simple messages', () {
|
||||
checkEncodeDecode<String>(string, null);
|
||||
checkEncodeDecode<String>(string, '');
|
||||
checkEncodeDecode<String>(string, 'hello');
|
||||
checkEncodeDecode<String>(string, 'special chars >\u263A\u{1F602}<');
|
||||
checkEncodeDecode<String?>(string, null);
|
||||
checkEncodeDecode<String?>(string, '');
|
||||
checkEncodeDecode<String?>(string, 'hello');
|
||||
checkEncodeDecode<String?>(string, 'special chars >\u263A\u{1F602}<');
|
||||
});
|
||||
test('ByteData with offset', () {
|
||||
const MessageCodec<String> string = StringCodec();
|
||||
final ByteData helloWorldByteData = string.encodeMessage('hello world');
|
||||
final ByteData helloByteData = string.encodeMessage('hello');
|
||||
|
||||
const MessageCodec<String?> string = StringCodec();
|
||||
final ByteData helloWorldByteData = string.encodeMessage('hello world')!;
|
||||
final ByteData helloByteData = string.encodeMessage('hello')!;
|
||||
final ByteData offsetByteData = ByteData.view(
|
||||
helloWorldByteData.buffer,
|
||||
helloByteData.lengthInBytes,
|
||||
@ -97,7 +94,7 @@ void main() {
|
||||
e.details == 'errorDetails')));
|
||||
});
|
||||
test('should decode error envelope with native stacktrace.', () {
|
||||
final ByteData errorData = stringCodec.encodeMessage(json
|
||||
final ByteData? errorData = stringCodec.encodeMessage(json
|
||||
.encode(<dynamic>[
|
||||
'errorCode',
|
||||
'errorMessage',
|
||||
@ -105,7 +102,7 @@ void main() {
|
||||
'errorStacktrace'
|
||||
]));
|
||||
expect(
|
||||
() => jsonMethodCodec.decodeEnvelope(errorData),
|
||||
() => jsonMethodCodec.decodeEnvelope(errorData!),
|
||||
throwsA(predicate((PlatformException e) =>
|
||||
e is PlatformException && e.stacktrace == 'errorStacktrace')));
|
||||
});
|
||||
|
@ -23,9 +23,9 @@ void checkEncodeDecode<T>(MessageCodec<T> codec, T message) {
|
||||
expect(decoded, isNull);
|
||||
} else {
|
||||
expect(deepEquals(message, decoded), isTrue);
|
||||
final ByteData encodedAgain = codec.encodeMessage(decoded)!;
|
||||
final ByteData? encodedAgain = codec.encodeMessage(decoded);
|
||||
expect(
|
||||
encodedAgain.buffer.asUint8List(),
|
||||
encodedAgain!.buffer.asUint8List(),
|
||||
orderedEquals(encoded!.buffer.asUint8List()),
|
||||
);
|
||||
}
|
||||
|
@ -2,7 +2,6 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
// This file contains tests that are only supported by the Dart VM. For
|
||||
// example, on the Web there's no way to express large integers.
|
||||
|
@ -2,8 +2,6 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:flutter/services.dart';
|
||||
@ -15,24 +13,24 @@ void main() {
|
||||
TestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
group('BasicMessageChannel', () {
|
||||
const MessageCodec<String> string = StringCodec();
|
||||
const BasicMessageChannel<String> channel = BasicMessageChannel<String>('ch', string);
|
||||
const MessageCodec<String?> string = StringCodec();
|
||||
const BasicMessageChannel<String?> channel = BasicMessageChannel<String?>('ch', string);
|
||||
test('can send string message and get reply', () async {
|
||||
ServicesBinding.instance.defaultBinaryMessenger.setMockMessageHandler(
|
||||
ServicesBinding.instance!.defaultBinaryMessenger.setMockMessageHandler(
|
||||
'ch',
|
||||
(ByteData message) async => string.encodeMessage(string.decodeMessage(message) + ' world'),
|
||||
(ByteData? message) async => string.encodeMessage(string.decodeMessage(message)! + ' world'),
|
||||
);
|
||||
final String reply = await channel.send('hello');
|
||||
final String? reply = await channel.send('hello');
|
||||
expect(reply, equals('hello world'));
|
||||
});
|
||||
|
||||
test('can receive string message and send reply', () async {
|
||||
channel.setMessageHandler((String message) async => message + ' world');
|
||||
String reply;
|
||||
await ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage(
|
||||
channel.setMessageHandler((String? message) async => message! + ' world');
|
||||
String? reply;
|
||||
await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage(
|
||||
'ch',
|
||||
const StringCodec().encodeMessage('hello'),
|
||||
(ByteData replyBinary) {
|
||||
(ByteData? replyBinary) {
|
||||
reply = string.decodeMessage(replyBinary);
|
||||
},
|
||||
);
|
||||
@ -46,9 +44,9 @@ void main() {
|
||||
const MethodChannel channel = MethodChannel('ch7', jsonMethod);
|
||||
const OptionalMethodChannel optionalMethodChannel = OptionalMethodChannel('ch8', jsonMethod);
|
||||
test('can invoke method and get result', () async {
|
||||
ServicesBinding.instance.defaultBinaryMessenger.setMockMessageHandler(
|
||||
ServicesBinding.instance!.defaultBinaryMessenger.setMockMessageHandler(
|
||||
'ch7',
|
||||
(ByteData message) async {
|
||||
(ByteData? message) async {
|
||||
final Map<dynamic, dynamic> methodCall = jsonMessage.decodeMessage(message) as Map<dynamic, dynamic>;
|
||||
if (methodCall['method'] == 'sayHello') {
|
||||
return jsonMessage.encodeMessage(<dynamic>['${methodCall['args']} world']);
|
||||
@ -57,14 +55,14 @@ void main() {
|
||||
}
|
||||
},
|
||||
);
|
||||
final String result = await channel.invokeMethod('sayHello', 'hello');
|
||||
final String? result = await channel.invokeMethod('sayHello', 'hello');
|
||||
expect(result, equals('hello world'));
|
||||
});
|
||||
|
||||
test('can invoke list method and get result', () async {
|
||||
ServicesBinding.instance.defaultBinaryMessenger.setMockMessageHandler(
|
||||
ServicesBinding.instance!.defaultBinaryMessenger.setMockMessageHandler(
|
||||
'ch7',
|
||||
(ByteData message) async {
|
||||
(ByteData? message) async {
|
||||
final Map<dynamic, dynamic> methodCall = jsonMessage.decodeMessage(message) as Map<dynamic, dynamic>;
|
||||
if (methodCall['method'] == 'sayHello') {
|
||||
return jsonMessage.encodeMessage(<dynamic>[<String>['${methodCall['args']}', 'world']]);
|
||||
@ -78,9 +76,9 @@ void main() {
|
||||
});
|
||||
|
||||
test('can invoke list method and get null result', () async {
|
||||
ServicesBinding.instance.defaultBinaryMessenger.setMockMessageHandler(
|
||||
ServicesBinding.instance!.defaultBinaryMessenger.setMockMessageHandler(
|
||||
'ch7',
|
||||
(ByteData message) async {
|
||||
(ByteData? message) async {
|
||||
final Map<dynamic, dynamic> methodCall = jsonMessage.decodeMessage(message) as Map<dynamic, dynamic>;
|
||||
if (methodCall['method'] == 'sayHello') {
|
||||
return jsonMessage.encodeMessage(<dynamic>[null]);
|
||||
@ -93,9 +91,9 @@ void main() {
|
||||
});
|
||||
|
||||
test('can invoke map method and get result', () async {
|
||||
ServicesBinding.instance.defaultBinaryMessenger.setMockMessageHandler(
|
||||
ServicesBinding.instance!.defaultBinaryMessenger.setMockMessageHandler(
|
||||
'ch7',
|
||||
(ByteData message) async {
|
||||
(ByteData? message) async {
|
||||
final Map<dynamic, dynamic> methodCall = jsonMessage.decodeMessage(message) as Map<dynamic, dynamic>;
|
||||
if (methodCall['method'] == 'sayHello') {
|
||||
return jsonMessage.encodeMessage(<dynamic>[<String, String>{'${methodCall['args']}': 'world'}]);
|
||||
@ -109,9 +107,9 @@ void main() {
|
||||
});
|
||||
|
||||
test('can invoke map method and get null result', () async {
|
||||
ServicesBinding.instance.defaultBinaryMessenger.setMockMessageHandler(
|
||||
ServicesBinding.instance!.defaultBinaryMessenger.setMockMessageHandler(
|
||||
'ch7',
|
||||
(ByteData message) async {
|
||||
(ByteData? message) async {
|
||||
final Map<dynamic, dynamic> methodCall = jsonMessage.decodeMessage(message) as Map<dynamic, dynamic>;
|
||||
if (methodCall['method'] == 'sayHello') {
|
||||
return jsonMessage.encodeMessage(<dynamic>[null]);
|
||||
@ -124,9 +122,9 @@ void main() {
|
||||
});
|
||||
|
||||
test('can invoke method and get error', () async {
|
||||
ServicesBinding.instance.defaultBinaryMessenger.setMockMessageHandler(
|
||||
ServicesBinding.instance!.defaultBinaryMessenger.setMockMessageHandler(
|
||||
'ch7',
|
||||
(ByteData message) async {
|
||||
(ByteData? message) async {
|
||||
return jsonMessage.encodeMessage(<dynamic>[
|
||||
'bad',
|
||||
'Something happened',
|
||||
@ -147,9 +145,9 @@ void main() {
|
||||
});
|
||||
|
||||
test('can invoke unimplemented method', () async {
|
||||
ServicesBinding.instance.defaultBinaryMessenger.setMockMessageHandler(
|
||||
ServicesBinding.instance!.defaultBinaryMessenger.setMockMessageHandler(
|
||||
'ch7',
|
||||
(ByteData message) async => null,
|
||||
(ByteData? message) async => null,
|
||||
);
|
||||
try {
|
||||
await channel.invokeMethod<void>('sayHello', 'hello');
|
||||
@ -163,19 +161,19 @@ void main() {
|
||||
});
|
||||
|
||||
test('can invoke unimplemented method (optional)', () async {
|
||||
ServicesBinding.instance.defaultBinaryMessenger.setMockMessageHandler(
|
||||
ServicesBinding.instance!.defaultBinaryMessenger.setMockMessageHandler(
|
||||
'ch8',
|
||||
(ByteData message) async => null,
|
||||
(ByteData? message) async => null,
|
||||
);
|
||||
final String result = await optionalMethodChannel.invokeMethod<String>('sayHello', 'hello');
|
||||
final String? result = await optionalMethodChannel.invokeMethod<String>('sayHello', 'hello');
|
||||
expect(result, isNull);
|
||||
});
|
||||
|
||||
test('can handle method call with no registered plugin (setting before)', () async {
|
||||
channel.setMethodCallHandler(null);
|
||||
final ByteData call = jsonMethod.encodeMethodCall(const MethodCall('sayHello', 'hello'));
|
||||
ByteData envelope;
|
||||
await ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage('ch7', call, (ByteData result) {
|
||||
ByteData? envelope;
|
||||
await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage('ch7', call, (ByteData? result) {
|
||||
envelope = result;
|
||||
});
|
||||
await null; // just in case there's something async happening
|
||||
@ -184,8 +182,8 @@ void main() {
|
||||
|
||||
test('can handle method call with no registered plugin (setting after)', () async {
|
||||
final ByteData call = jsonMethod.encodeMethodCall(const MethodCall('sayHello', 'hello'));
|
||||
ByteData envelope;
|
||||
await ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage('ch7', call, (ByteData result) {
|
||||
ByteData? envelope;
|
||||
await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage('ch7', call, (ByteData? result) {
|
||||
envelope = result;
|
||||
});
|
||||
channel.setMethodCallHandler(null);
|
||||
@ -198,8 +196,8 @@ void main() {
|
||||
throw MissingPluginException();
|
||||
});
|
||||
final ByteData call = jsonMethod.encodeMethodCall(const MethodCall('sayHello', 'hello'));
|
||||
ByteData envelope;
|
||||
await ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage('ch7', call, (ByteData result) {
|
||||
ByteData? envelope;
|
||||
await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage('ch7', call, (ByteData? result) {
|
||||
envelope = result;
|
||||
});
|
||||
expect(envelope, isNull);
|
||||
@ -208,11 +206,11 @@ void main() {
|
||||
test('can handle method call with successful result', () async {
|
||||
channel.setMethodCallHandler((MethodCall call) async => '${call.arguments}, world');
|
||||
final ByteData call = jsonMethod.encodeMethodCall(const MethodCall('sayHello', 'hello'));
|
||||
ByteData envelope;
|
||||
await ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage('ch7', call, (ByteData result) {
|
||||
ByteData? envelope;
|
||||
await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage('ch7', call, (ByteData? result) {
|
||||
envelope = result;
|
||||
});
|
||||
expect(jsonMethod.decodeEnvelope(envelope), equals('hello, world'));
|
||||
expect(jsonMethod.decodeEnvelope(envelope!), equals('hello, world'));
|
||||
});
|
||||
|
||||
test('can handle method call with expressive error result', () async {
|
||||
@ -220,12 +218,12 @@ void main() {
|
||||
throw PlatformException(code: 'bad', message: 'sayHello failed', details: null);
|
||||
});
|
||||
final ByteData call = jsonMethod.encodeMethodCall(const MethodCall('sayHello', 'hello'));
|
||||
ByteData envelope;
|
||||
await ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage('ch7', call, (ByteData result) {
|
||||
ByteData? envelope;
|
||||
await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage('ch7', call, (ByteData? result) {
|
||||
envelope = result;
|
||||
});
|
||||
try {
|
||||
jsonMethod.decodeEnvelope(envelope);
|
||||
jsonMethod.decodeEnvelope(envelope!);
|
||||
fail('Exception expected');
|
||||
} on PlatformException catch (e) {
|
||||
expect(e.code, equals('bad'));
|
||||
@ -240,12 +238,12 @@ void main() {
|
||||
throw ArgumentError('bad');
|
||||
});
|
||||
final ByteData call = jsonMethod.encodeMethodCall(const MethodCall('sayHello', 'hello'));
|
||||
ByteData envelope;
|
||||
await ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage('ch7', call, (ByteData result) {
|
||||
ByteData? envelope;
|
||||
await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage('ch7', call, (ByteData? result) {
|
||||
envelope = result;
|
||||
});
|
||||
try {
|
||||
jsonMethod.decodeEnvelope(envelope);
|
||||
jsonMethod.decodeEnvelope(envelope!);
|
||||
fail('Exception expected');
|
||||
} on PlatformException catch (e) {
|
||||
expect(e.code, equals('error'));
|
||||
@ -280,18 +278,18 @@ void main() {
|
||||
const MessageCodec<dynamic> jsonMessage = JSONMessageCodec();
|
||||
const MethodCodec jsonMethod = JSONMethodCodec();
|
||||
const EventChannel channel = EventChannel('ch', jsonMethod);
|
||||
void emitEvent(ByteData event) {
|
||||
ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage(
|
||||
void emitEvent(ByteData? event) {
|
||||
ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage(
|
||||
'ch',
|
||||
event,
|
||||
(ByteData reply) { },
|
||||
(ByteData? reply) {},
|
||||
);
|
||||
}
|
||||
test('can receive event stream', () async {
|
||||
bool canceled = false;
|
||||
ServicesBinding.instance.defaultBinaryMessenger.setMockMessageHandler(
|
||||
ServicesBinding.instance!.defaultBinaryMessenger.setMockMessageHandler(
|
||||
'ch',
|
||||
(ByteData message) async {
|
||||
(ByteData? message) async {
|
||||
final Map<dynamic, dynamic> methodCall = jsonMessage.decodeMessage(message) as Map<dynamic, dynamic>;
|
||||
if (methodCall['method'] == 'listen') {
|
||||
final String argument = methodCall['args'] as String;
|
||||
@ -314,9 +312,9 @@ void main() {
|
||||
});
|
||||
|
||||
test('can receive error event', () async {
|
||||
ServicesBinding.instance.defaultBinaryMessenger.setMockMessageHandler(
|
||||
ServicesBinding.instance!.defaultBinaryMessenger.setMockMessageHandler(
|
||||
'ch',
|
||||
(ByteData message) async {
|
||||
(ByteData? message) async {
|
||||
final Map<dynamic, dynamic> methodCall = jsonMessage.decodeMessage(message) as Map<dynamic, dynamic>;
|
||||
if (methodCall['method'] == 'listen') {
|
||||
final String argument = methodCall['args'] as String;
|
||||
|
@ -2,7 +2,6 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
@TestOn('!chrome') // missing web infrastructure for plugins.
|
||||
|
||||
@ -16,20 +15,20 @@ void main() {
|
||||
// Initialize all bindings because defaultBinaryMessenger.send() needs a window.
|
||||
TestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
final List<ByteData> log = <ByteData>[];
|
||||
final List<ByteData?> log = <ByteData>[];
|
||||
|
||||
ServicesBinding.instance.defaultBinaryMessenger.setMockMessageHandler('test1', (ByteData message) async {
|
||||
ServicesBinding.instance!.defaultBinaryMessenger.setMockMessageHandler('test1', (ByteData? message) async {
|
||||
log.add(message);
|
||||
return null;
|
||||
});
|
||||
|
||||
final ByteData message = ByteData(2)..setUint16(0, 0xABCD);
|
||||
await ServicesBinding.instance.defaultBinaryMessenger.send('test1', message);
|
||||
await ServicesBinding.instance!.defaultBinaryMessenger.send('test1', message);
|
||||
expect(log, equals(<ByteData>[message]));
|
||||
log.clear();
|
||||
|
||||
ServicesBinding.instance.defaultBinaryMessenger.setMockMessageHandler('test1', null);
|
||||
await ServicesBinding.instance.defaultBinaryMessenger.send('test1', message);
|
||||
ServicesBinding.instance!.defaultBinaryMessenger.setMockMessageHandler('test1', null);
|
||||
await ServicesBinding.instance!.defaultBinaryMessenger.send('test1', message);
|
||||
expect(log, isEmpty);
|
||||
});
|
||||
}
|
||||
|
@ -2,7 +2,6 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'package:flutter/painting.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
@ -15,7 +14,7 @@ void main() {
|
||||
TestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
group('Android', () {
|
||||
FakeAndroidPlatformViewsController viewsController;
|
||||
late FakeAndroidPlatformViewsController viewsController;
|
||||
setUp(() {
|
||||
viewsController = FakeAndroidPlatformViewsController();
|
||||
});
|
||||
@ -202,7 +201,7 @@ void main() {
|
||||
});
|
||||
|
||||
group('iOS', () {
|
||||
FakeIosPlatformViewsController viewsController;
|
||||
late FakeIosPlatformViewsController viewsController;
|
||||
setUp(() {
|
||||
viewsController = FakeIosPlatformViewsController();
|
||||
});
|
||||
|
@ -2,7 +2,6 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
@ -209,10 +208,10 @@ void main() {
|
||||
// when this event is received, but it's not in keysPressed yet.
|
||||
data['modifiers'] |= RawKeyEventDataMacOs.modifierLeftShift | RawKeyEventDataMacOs.modifierShift;
|
||||
// dispatch the modified data.
|
||||
await ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage(
|
||||
await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage(
|
||||
SystemChannels.keyEvent.name,
|
||||
SystemChannels.keyEvent.codec.encodeMessage(data),
|
||||
(ByteData data) {},
|
||||
(ByteData? data) {},
|
||||
);
|
||||
expect(
|
||||
RawKeyboard.instance.keysPressed,
|
||||
@ -234,10 +233,10 @@ void main() {
|
||||
// when this event is received, but it's not in keysPressed yet.
|
||||
data['modifiers'] |= RawKeyEventDataWindows.modifierLeftShift | RawKeyEventDataWindows.modifierShift;
|
||||
// dispatch the modified data.
|
||||
await ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage(
|
||||
await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage(
|
||||
SystemChannels.keyEvent.name,
|
||||
SystemChannels.keyEvent.codec.encodeMessage(data),
|
||||
(ByteData data) {},
|
||||
(ByteData? data) {},
|
||||
);
|
||||
expect(
|
||||
RawKeyboard.instance.keysPressed,
|
||||
@ -259,10 +258,10 @@ void main() {
|
||||
// when this event is received, but it's not in keysPressed yet.
|
||||
data['metaState'] |= RawKeyEventDataAndroid.modifierLeftShift | RawKeyEventDataAndroid.modifierShift;
|
||||
// dispatch the modified data.
|
||||
await ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage(
|
||||
await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage(
|
||||
SystemChannels.keyEvent.name,
|
||||
SystemChannels.keyEvent.codec.encodeMessage(data),
|
||||
(ByteData data) {},
|
||||
(ByteData? data) {},
|
||||
);
|
||||
expect(
|
||||
RawKeyboard.instance.keysPressed,
|
||||
@ -284,10 +283,10 @@ void main() {
|
||||
// when this event is received, but it's not in keysPressed yet.
|
||||
data['modifiers'] |= RawKeyEventDataFuchsia.modifierLeftShift;
|
||||
// dispatch the modified data.
|
||||
await ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage(
|
||||
await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage(
|
||||
SystemChannels.keyEvent.name,
|
||||
SystemChannels.keyEvent.codec.encodeMessage(data),
|
||||
(ByteData data) {},
|
||||
(ByteData? data) {},
|
||||
);
|
||||
expect(
|
||||
RawKeyboard.instance.keysPressed,
|
||||
@ -309,10 +308,10 @@ void main() {
|
||||
// when this event is received, but it's not in keysPressed yet.
|
||||
data['modifiers'] |= GLFWKeyHelper.modifierShift;
|
||||
// dispatch the modified data.
|
||||
await ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage(
|
||||
await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage(
|
||||
SystemChannels.keyEvent.name,
|
||||
SystemChannels.keyEvent.codec.encodeMessage(data),
|
||||
(ByteData data) {},
|
||||
(ByteData? data) {},
|
||||
);
|
||||
expect(
|
||||
RawKeyboard.instance.keysPressed,
|
||||
@ -343,10 +342,10 @@ void main() {
|
||||
RawKeyEventDataAndroid.modifierControl |
|
||||
RawKeyEventDataAndroid.modifierMeta;
|
||||
// dispatch the modified data.
|
||||
await ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage(
|
||||
await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage(
|
||||
SystemChannels.keyEvent.name,
|
||||
SystemChannels.keyEvent.codec.encodeMessage(data),
|
||||
(ByteData data) {},
|
||||
(ByteData? data) {},
|
||||
);
|
||||
expect(
|
||||
RawKeyboard.instance.keysPressed,
|
||||
@ -381,10 +380,10 @@ void main() {
|
||||
RawKeyEventDataMacOs.modifierCommand |
|
||||
RawKeyEventDataMacOs.modifierControl;
|
||||
// dispatch the modified data.
|
||||
await ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage(
|
||||
await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage(
|
||||
SystemChannels.keyEvent.name,
|
||||
SystemChannels.keyEvent.codec.encodeMessage(data),
|
||||
(ByteData data) {},
|
||||
(ByteData? data) {},
|
||||
);
|
||||
expect(
|
||||
RawKeyboard.instance.keysPressed,
|
||||
@ -419,10 +418,10 @@ void main() {
|
||||
RawKeyEventDataWindows.modifierAlt |
|
||||
RawKeyEventDataWindows.modifierControl;
|
||||
// dispatch the modified data.
|
||||
await ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage(
|
||||
await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage(
|
||||
SystemChannels.keyEvent.name,
|
||||
SystemChannels.keyEvent.codec.encodeMessage(data),
|
||||
(ByteData data) {},
|
||||
(ByteData? data) {},
|
||||
);
|
||||
expect(
|
||||
RawKeyboard.instance.keysPressed,
|
||||
@ -456,10 +455,10 @@ void main() {
|
||||
GLFWKeyHelper.modifierControl |
|
||||
GLFWKeyHelper.modifierMeta;
|
||||
// dispatch the modified data.
|
||||
await ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage(
|
||||
await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage(
|
||||
SystemChannels.keyEvent.name,
|
||||
SystemChannels.keyEvent.codec.encodeMessage(data),
|
||||
(ByteData data) {},
|
||||
(ByteData? data) {},
|
||||
);
|
||||
expect(
|
||||
RawKeyboard.instance.keysPressed,
|
||||
@ -480,13 +479,13 @@ void main() {
|
||||
});
|
||||
|
||||
testWidgets('RawKeyboard asserts if no keys are in keysPressed after receiving a key down event', (WidgetTester tester) async {
|
||||
FlutterErrorDetails errorDetails;
|
||||
final FlutterExceptionHandler oldHandler = FlutterError.onError;
|
||||
FlutterErrorDetails? errorDetails;
|
||||
final FlutterExceptionHandler? oldHandler = FlutterError.onError;
|
||||
FlutterError.onError = (FlutterErrorDetails details) {
|
||||
errorDetails = details;
|
||||
};
|
||||
try {
|
||||
await ServicesBinding.instance.defaultBinaryMessenger
|
||||
await ServicesBinding.instance!.defaultBinaryMessenger
|
||||
.handlePlatformMessage(
|
||||
SystemChannels.keyEvent.name,
|
||||
SystemChannels.keyEvent.codec.encodeMessage(const <String, dynamic>{
|
||||
@ -498,13 +497,13 @@ void main() {
|
||||
'source': 0x101,
|
||||
'deviceId': 1,
|
||||
}),
|
||||
(ByteData data) {},
|
||||
(ByteData? data) {},
|
||||
);
|
||||
} finally {
|
||||
FlutterError.onError = oldHandler;
|
||||
}
|
||||
expect(errorDetails, isNotNull);
|
||||
expect(errorDetails.stack, 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'));
|
||||
});
|
||||
@ -542,16 +541,16 @@ void main() {
|
||||
});
|
||||
final RawKeyEventDataAndroid data = event.data as RawKeyEventDataAndroid;
|
||||
for (final ModifierKey key in ModifierKey.values) {
|
||||
if (modifierTests[modifier].key == key) {
|
||||
if (modifierTests[modifier]!.key == key) {
|
||||
expect(
|
||||
data.isModifierPressed(key, side: modifierTests[modifier].side),
|
||||
data.isModifierPressed(key, side: modifierTests[modifier]!.side),
|
||||
isTrue,
|
||||
reason: "$key should be pressed with metaState $modifier, but isn't.",
|
||||
);
|
||||
expect(data.getModifierSide(key), equals(modifierTests[modifier].side));
|
||||
expect(data.getModifierSide(key), equals(modifierTests[modifier]!.side));
|
||||
} else {
|
||||
expect(
|
||||
data.isModifierPressed(key, side: modifierTests[modifier].side),
|
||||
data.isModifierPressed(key, side: modifierTests[modifier]!.side),
|
||||
isFalse,
|
||||
reason: '$key should not be pressed with metaState $modifier.',
|
||||
);
|
||||
@ -578,21 +577,21 @@ void main() {
|
||||
});
|
||||
final RawKeyEventDataAndroid data = event.data as RawKeyEventDataAndroid;
|
||||
for (final ModifierKey key in ModifierKey.values) {
|
||||
if (modifierTests[modifier].key == key || key == ModifierKey.functionModifier) {
|
||||
if (modifierTests[modifier]!.key == key || key == ModifierKey.functionModifier) {
|
||||
expect(
|
||||
data.isModifierPressed(key, side: modifierTests[modifier].side),
|
||||
data.isModifierPressed(key, side: modifierTests[modifier]!.side),
|
||||
isTrue,
|
||||
reason: '$key should be pressed with metaState $modifier '
|
||||
"and additional key ${RawKeyEventDataAndroid.modifierFunction}, but isn't.",
|
||||
);
|
||||
if (key != ModifierKey.functionModifier) {
|
||||
expect(data.getModifierSide(key), equals(modifierTests[modifier].side));
|
||||
expect(data.getModifierSide(key), equals(modifierTests[modifier]!.side));
|
||||
} else {
|
||||
expect(data.getModifierSide(key), equals(KeyboardSide.all));
|
||||
}
|
||||
} else {
|
||||
expect(
|
||||
data.isModifierPressed(key, side: modifierTests[modifier].side),
|
||||
data.isModifierPressed(key, side: modifierTests[modifier]!.side),
|
||||
isFalse,
|
||||
reason: '$key should not be pressed with metaState $modifier '
|
||||
'and additional key ${RawKeyEventDataAndroid.modifierFunction}.',
|
||||
@ -741,11 +740,11 @@ void main() {
|
||||
platform: 'android',
|
||||
isDown: true,
|
||||
);
|
||||
Map<String, dynamic> message;
|
||||
await ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage(
|
||||
Map<String, dynamic>? message;
|
||||
await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage(
|
||||
SystemChannels.keyEvent.name,
|
||||
SystemChannels.keyEvent.codec.encodeMessage(data),
|
||||
(ByteData data) {
|
||||
(ByteData? data) {
|
||||
message = SystemChannels.keyEvent.codec.decodeMessage(data) as Map<String, dynamic>;
|
||||
},
|
||||
);
|
||||
@ -765,15 +764,15 @@ void main() {
|
||||
focusNode.requestFocus();
|
||||
await tester.pump();
|
||||
|
||||
await ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage(
|
||||
await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage(
|
||||
SystemChannels.keyEvent.name,
|
||||
SystemChannels.keyEvent.codec.encodeMessage(data),
|
||||
(ByteData data) {
|
||||
(ByteData? data) {
|
||||
message = SystemChannels.keyEvent.codec.decodeMessage(data) as Map<String, dynamic>;
|
||||
},
|
||||
);
|
||||
expect(message, equals(<String, dynamic>{ 'handled': true }));
|
||||
ServicesBinding.instance.defaultBinaryMessenger.setMockMessageHandler(SystemChannels.keyEvent.name, null);
|
||||
ServicesBinding.instance!.defaultBinaryMessenger.setMockMessageHandler(SystemChannels.keyEvent.name, null);
|
||||
});
|
||||
});
|
||||
group('RawKeyEventDataFuchsia', () {
|
||||
@ -804,15 +803,15 @@ void main() {
|
||||
});
|
||||
final RawKeyEventDataFuchsia data = event.data as RawKeyEventDataFuchsia;
|
||||
for (final ModifierKey key in ModifierKey.values) {
|
||||
if (modifierTests[modifier].key == key) {
|
||||
if (modifierTests[modifier]!.key == key) {
|
||||
expect(
|
||||
data.isModifierPressed(key, side: modifierTests[modifier].side),
|
||||
data.isModifierPressed(key, side: modifierTests[modifier]!.side),
|
||||
isTrue,
|
||||
reason: "$key should be pressed with metaState $modifier, but isn't.",
|
||||
);
|
||||
} else {
|
||||
expect(
|
||||
data.isModifierPressed(key, side: modifierTests[modifier].side),
|
||||
data.isModifierPressed(key, side: modifierTests[modifier]!.side),
|
||||
isFalse,
|
||||
reason: '$key should not be pressed with metaState $modifier.',
|
||||
);
|
||||
@ -835,16 +834,16 @@ void main() {
|
||||
});
|
||||
final RawKeyEventDataFuchsia data = event.data as RawKeyEventDataFuchsia;
|
||||
for (final ModifierKey key in ModifierKey.values) {
|
||||
if (modifierTests[modifier].key == key || key == ModifierKey.capsLockModifier) {
|
||||
if (modifierTests[modifier]!.key == key || key == ModifierKey.capsLockModifier) {
|
||||
expect(
|
||||
data.isModifierPressed(key, side: modifierTests[modifier].side),
|
||||
data.isModifierPressed(key, side: modifierTests[modifier]!.side),
|
||||
isTrue,
|
||||
reason: '$key should be pressed with metaState $modifier '
|
||||
"and additional key ${RawKeyEventDataFuchsia.modifierCapsLock}, but isn't.",
|
||||
);
|
||||
} else {
|
||||
expect(
|
||||
data.isModifierPressed(key, side: modifierTests[modifier].side),
|
||||
data.isModifierPressed(key, side: modifierTests[modifier]!.side),
|
||||
isFalse,
|
||||
reason: '$key should not be pressed with metaState $modifier '
|
||||
'and additional key ${RawKeyEventDataFuchsia.modifierCapsLock}.',
|
||||
@ -920,16 +919,16 @@ void main() {
|
||||
});
|
||||
final RawKeyEventDataMacOs data = event.data as RawKeyEventDataMacOs;
|
||||
for (final ModifierKey key in ModifierKey.values) {
|
||||
if (modifierTests[modifier].key == key) {
|
||||
if (modifierTests[modifier]!.key == key) {
|
||||
expect(
|
||||
data.isModifierPressed(key, side: modifierTests[modifier].side),
|
||||
data.isModifierPressed(key, side: modifierTests[modifier]!.side),
|
||||
isTrue,
|
||||
reason: "$key should be pressed with metaState $modifier, but isn't.",
|
||||
);
|
||||
expect(data.getModifierSide(key), equals(modifierTests[modifier].side));
|
||||
expect(data.getModifierSide(key), equals(modifierTests[modifier]!.side));
|
||||
} else {
|
||||
expect(
|
||||
data.isModifierPressed(key, side: modifierTests[modifier].side),
|
||||
data.isModifierPressed(key, side: modifierTests[modifier]!.side),
|
||||
isFalse,
|
||||
reason: '$key should not be pressed with metaState $modifier.',
|
||||
);
|
||||
@ -954,21 +953,21 @@ void main() {
|
||||
});
|
||||
final RawKeyEventDataMacOs data = event.data as RawKeyEventDataMacOs;
|
||||
for (final ModifierKey key in ModifierKey.values) {
|
||||
if (modifierTests[modifier].key == key || key == ModifierKey.capsLockModifier) {
|
||||
if (modifierTests[modifier]!.key == key || key == ModifierKey.capsLockModifier) {
|
||||
expect(
|
||||
data.isModifierPressed(key, side: modifierTests[modifier].side),
|
||||
data.isModifierPressed(key, side: modifierTests[modifier]!.side),
|
||||
isTrue,
|
||||
reason: '$key should be pressed with metaState $modifier '
|
||||
"and additional key ${RawKeyEventDataMacOs.modifierCapsLock}, but isn't.",
|
||||
);
|
||||
if (key != ModifierKey.capsLockModifier) {
|
||||
expect(data.getModifierSide(key), equals(modifierTests[modifier].side));
|
||||
expect(data.getModifierSide(key), equals(modifierTests[modifier]!.side));
|
||||
} else {
|
||||
expect(data.getModifierSide(key), equals(KeyboardSide.all));
|
||||
}
|
||||
} else {
|
||||
expect(
|
||||
data.isModifierPressed(key, side: modifierTests[modifier].side),
|
||||
data.isModifierPressed(key, side: modifierTests[modifier]!.side),
|
||||
isFalse,
|
||||
reason: '$key should not be pressed with metaState $modifier '
|
||||
'and additional key ${RawKeyEventDataMacOs.modifierCapsLock}.',
|
||||
@ -1068,16 +1067,16 @@ void main() {
|
||||
});
|
||||
final RawKeyEventDataWindows data = event.data as RawKeyEventDataWindows;
|
||||
for (final ModifierKey key in ModifierKey.values) {
|
||||
if (modifierTests[modifier].key == key) {
|
||||
if (modifierTests[modifier]!.key == key) {
|
||||
expect(
|
||||
data.isModifierPressed(key, side: modifierTests[modifier].side),
|
||||
data.isModifierPressed(key, side: modifierTests[modifier]!.side),
|
||||
isTrue,
|
||||
reason: "$key should be pressed with modifier $modifier, but isn't.",
|
||||
);
|
||||
expect(data.getModifierSide(key), equals(modifierTests[modifier].side));
|
||||
expect(data.getModifierSide(key), equals(modifierTests[modifier]!.side));
|
||||
} else {
|
||||
expect(
|
||||
data.isModifierPressed(key, side: modifierTests[modifier].side),
|
||||
data.isModifierPressed(key, side: modifierTests[modifier]!.side),
|
||||
isFalse,
|
||||
reason: '$key should not be pressed with metaState $modifier.',
|
||||
);
|
||||
@ -1101,21 +1100,21 @@ void main() {
|
||||
});
|
||||
final RawKeyEventDataWindows data = event.data as RawKeyEventDataWindows;
|
||||
for (final ModifierKey key in ModifierKey.values) {
|
||||
if (modifierTests[modifier].key == key || key == ModifierKey.capsLockModifier) {
|
||||
if (modifierTests[modifier]!.key == key || key == ModifierKey.capsLockModifier) {
|
||||
expect(
|
||||
data.isModifierPressed(key, side: modifierTests[modifier].side),
|
||||
data.isModifierPressed(key, side: modifierTests[modifier]!.side),
|
||||
isTrue,
|
||||
reason: '$key should be pressed with metaState $modifier '
|
||||
"and additional key ${RawKeyEventDataWindows.modifierCaps}, but isn't.",
|
||||
);
|
||||
if (key != ModifierKey.capsLockModifier) {
|
||||
expect(data.getModifierSide(key), equals(modifierTests[modifier].side));
|
||||
expect(data.getModifierSide(key), equals(modifierTests[modifier]!.side));
|
||||
} else {
|
||||
expect(data.getModifierSide(key), equals(KeyboardSide.all));
|
||||
}
|
||||
} else {
|
||||
expect(
|
||||
data.isModifierPressed(key, side: modifierTests[modifier].side),
|
||||
data.isModifierPressed(key, side: modifierTests[modifier]!.side),
|
||||
isFalse,
|
||||
reason: '$key should not be pressed with metaState $modifier '
|
||||
'and additional key ${RawKeyEventDataWindows.modifierCaps}.',
|
||||
@ -1194,7 +1193,7 @@ void main() {
|
||||
};
|
||||
|
||||
// How modifiers are interpreted depends upon the keyCode for GLFW.
|
||||
int keyCodeForModifier(int modifier, {bool isLeft}) {
|
||||
int keyCodeForModifier(int modifier, {required bool isLeft}) {
|
||||
switch (modifier) {
|
||||
case GLFWKeyHelper.modifierAlt:
|
||||
return isLeft ? 342 : 346;
|
||||
@ -1229,16 +1228,16 @@ void main() {
|
||||
});
|
||||
final RawKeyEventDataLinux data = event.data as RawKeyEventDataLinux;
|
||||
for (final ModifierKey key in ModifierKey.values) {
|
||||
if (modifierTests[modifier].key == key) {
|
||||
if (modifierTests[modifier]!.key == key) {
|
||||
expect(
|
||||
data.isModifierPressed(key, side: modifierTests[modifier].side),
|
||||
data.isModifierPressed(key, side: modifierTests[modifier]!.side),
|
||||
isDown ? isTrue : isFalse,
|
||||
reason: "${isLeft ? 'left' : 'right'} $key ${isDown ? 'should' : 'should not'} be pressed with metaState $modifier, when key is ${isDown ? 'down' : 'up'}, but isn't.",
|
||||
);
|
||||
expect(data.getModifierSide(key), equals(modifierTests[modifier].side));
|
||||
expect(data.getModifierSide(key), equals(modifierTests[modifier]!.side));
|
||||
} else {
|
||||
expect(
|
||||
data.isModifierPressed(key, side: modifierTests[modifier].side),
|
||||
data.isModifierPressed(key, side: modifierTests[modifier]!.side),
|
||||
isFalse,
|
||||
reason: "${isLeft ? 'left' : 'right'} $key should not be pressed with metaState $modifier, wwhen key is ${isDown ? 'down' : 'up'}, but is.",
|
||||
);
|
||||
@ -1265,21 +1264,21 @@ void main() {
|
||||
});
|
||||
final RawKeyEventDataLinux data = event.data as RawKeyEventDataLinux;
|
||||
for (final ModifierKey key in ModifierKey.values) {
|
||||
if (modifierTests[modifier].key == key || key == ModifierKey.controlModifier) {
|
||||
if (modifierTests[modifier]!.key == key || key == ModifierKey.controlModifier) {
|
||||
expect(
|
||||
data.isModifierPressed(key, side: modifierTests[modifier].side),
|
||||
data.isModifierPressed(key, side: modifierTests[modifier]!.side),
|
||||
isTrue,
|
||||
reason: '$key should be pressed with metaState $modifier '
|
||||
"and additional key ${GLFWKeyHelper.modifierControl}, but isn't.",
|
||||
);
|
||||
if (key != ModifierKey.controlModifier) {
|
||||
expect(data.getModifierSide(key), equals(modifierTests[modifier].side));
|
||||
expect(data.getModifierSide(key), equals(modifierTests[modifier]!.side));
|
||||
} else {
|
||||
expect(data.getModifierSide(key), equals(KeyboardSide.all));
|
||||
}
|
||||
} else {
|
||||
expect(
|
||||
data.isModifierPressed(key, side: modifierTests[modifier].side),
|
||||
data.isModifierPressed(key, side: modifierTests[modifier]!.side),
|
||||
isFalse,
|
||||
reason: '$key should not be pressed with metaState $modifier '
|
||||
'and additional key ${GLFWKeyHelper.modifierControl}.',
|
||||
@ -1378,7 +1377,7 @@ void main() {
|
||||
};
|
||||
|
||||
// How modifiers are interpreted depends upon the keyCode for GTK.
|
||||
int keyCodeForModifier(int modifier, {bool isLeft}) {
|
||||
int keyCodeForModifier(int modifier, {required bool isLeft}) {
|
||||
switch (modifier) {
|
||||
case GtkKeyHelper.modifierMod1:
|
||||
return isLeft ? 65513 : 65513;
|
||||
@ -1413,16 +1412,16 @@ void main() {
|
||||
});
|
||||
final RawKeyEventDataLinux data = event.data as RawKeyEventDataLinux;
|
||||
for (final ModifierKey key in ModifierKey.values) {
|
||||
if (modifierTests[modifier].key == key) {
|
||||
if (modifierTests[modifier]!.key == key) {
|
||||
expect(
|
||||
data.isModifierPressed(key, side: modifierTests[modifier].side),
|
||||
data.isModifierPressed(key, side: modifierTests[modifier]!.side),
|
||||
isDown ? isTrue : isFalse,
|
||||
reason: "${isLeft ? 'left' : 'right'} $key ${isDown ? 'should' : 'should not'} be pressed with metaState $modifier, when key is ${isDown ? 'down' : 'up'}, but isn't.",
|
||||
);
|
||||
expect(data.getModifierSide(key), equals(modifierTests[modifier].side));
|
||||
expect(data.getModifierSide(key), equals(modifierTests[modifier]!.side));
|
||||
} else {
|
||||
expect(
|
||||
data.isModifierPressed(key, side: modifierTests[modifier].side),
|
||||
data.isModifierPressed(key, side: modifierTests[modifier]!.side),
|
||||
isFalse,
|
||||
reason: "${isLeft ? 'left' : 'right'} $key should not be pressed with metaState $modifier, wwhen key is ${isDown ? 'down' : 'up'}, but is.",
|
||||
);
|
||||
@ -1449,21 +1448,21 @@ void main() {
|
||||
});
|
||||
final RawKeyEventDataLinux data = event.data as RawKeyEventDataLinux;
|
||||
for (final ModifierKey key in ModifierKey.values) {
|
||||
if (modifierTests[modifier].key == key || key == ModifierKey.controlModifier) {
|
||||
if (modifierTests[modifier]!.key == key || key == ModifierKey.controlModifier) {
|
||||
expect(
|
||||
data.isModifierPressed(key, side: modifierTests[modifier].side),
|
||||
data.isModifierPressed(key, side: modifierTests[modifier]!.side),
|
||||
isTrue,
|
||||
reason: '$key should be pressed with metaState $modifier '
|
||||
"and additional key ${GtkKeyHelper.modifierControl}, but isn't.",
|
||||
);
|
||||
if (key != ModifierKey.controlModifier) {
|
||||
expect(data.getModifierSide(key), equals(modifierTests[modifier].side));
|
||||
expect(data.getModifierSide(key), equals(modifierTests[modifier]!.side));
|
||||
} else {
|
||||
expect(data.getModifierSide(key), equals(KeyboardSide.all));
|
||||
}
|
||||
} else {
|
||||
expect(
|
||||
data.isModifierPressed(key, side: modifierTests[modifier].side),
|
||||
data.isModifierPressed(key, side: modifierTests[modifier]!.side),
|
||||
isFalse,
|
||||
reason: '$key should not be pressed with metaState $modifier '
|
||||
'and additional key ${GtkKeyHelper.modifierControl}.',
|
||||
|
@ -2,7 +2,6 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
@ -54,7 +53,7 @@ void main() {
|
||||
expect(manager.updateScheduled, isFalse);
|
||||
|
||||
// Can store null.
|
||||
bucket.write<bool>('value4', null);
|
||||
bucket.write<bool?>('value4', null);
|
||||
expect(manager.updateScheduled, isTrue);
|
||||
expect(bucket.read<int>('value4'), null);
|
||||
manager.doSerialization();
|
||||
@ -111,7 +110,7 @@ void main() {
|
||||
expect(manager.updateScheduled, isFalse);
|
||||
|
||||
// Can store null.
|
||||
child.write<bool>('value4', null);
|
||||
child.write<bool?>('value4', null);
|
||||
expect(manager.updateScheduled, isTrue);
|
||||
expect(child.read<int>('value4'), null);
|
||||
manager.doSerialization();
|
||||
@ -327,7 +326,7 @@ void main() {
|
||||
final RestorationBucket root = RestorationBucket.root(manager: manager, rawData: rawData);
|
||||
|
||||
final RestorationBucket child = root.claimChild('child1', debugOwner: 'owner1');
|
||||
final Object rawChildData = rawData[childrenMapKey]['child1'];
|
||||
final Object rawChildData = rawData[childrenMapKey]['child1'] as Object;
|
||||
expect(rawChildData, isNotNull);
|
||||
|
||||
expect(manager.updateScheduled, isFalse);
|
||||
@ -370,9 +369,9 @@ void main() {
|
||||
final RestorationBucket child2 = root.claimChild('child2', debugOwner: 'owner1');
|
||||
manager.doSerialization();
|
||||
|
||||
final Object rawChild1Data = rawData[childrenMapKey]['child1'];
|
||||
final Object rawChild1Data = rawData[childrenMapKey]['child1'] as Object;
|
||||
expect(rawChild1Data, isNotNull);
|
||||
final Object rawChild2Data = rawData[childrenMapKey]['child2'];
|
||||
final Object rawChild2Data = rawData[childrenMapKey]['child2'] as Object;
|
||||
expect(rawChild2Data, isNotNull);
|
||||
|
||||
expect(child1.restorationId, 'child1');
|
||||
@ -396,7 +395,7 @@ void main() {
|
||||
final Map<String, dynamic> rawData = _createRawDataSet();
|
||||
final RestorationBucket root = RestorationBucket.root(manager: manager, rawData: rawData);
|
||||
|
||||
final Object rawChild1Data = rawData[childrenMapKey]['child1'];
|
||||
final Object rawChild1Data = rawData[childrenMapKey]['child1'] as Object;
|
||||
expect(rawChild1Data, isNotNull);
|
||||
|
||||
final RestorationBucket child1 = root.claimChild('child1', debugOwner: 'owner1');
|
||||
@ -462,7 +461,7 @@ void main() {
|
||||
manager.doSerialization();
|
||||
expect(manager.updateScheduled, isFalse);
|
||||
|
||||
final Object childOfChildData = rawData[childrenMapKey]['child1'][childrenMapKey]['childOfChild'];
|
||||
final Object childOfChildData = rawData[childrenMapKey]['child1'][childrenMapKey]['childOfChild'] as Object;
|
||||
expect(childOfChildData, isNotEmpty);
|
||||
|
||||
root.adoptChild(childOfChild);
|
||||
@ -497,7 +496,7 @@ void main() {
|
||||
final RestorationBucket childOfChild = child.claimChild('child1', debugOwner: 'owner2');
|
||||
childOfChild.write<String>('foo', 'bar');
|
||||
|
||||
final Object childOfChildData = rawData[childrenMapKey]['child1'][childrenMapKey]['child1'];
|
||||
final Object childOfChildData = rawData[childrenMapKey]['child1'][childrenMapKey]['child1'] as Object;
|
||||
expect(childOfChildData, isNotEmpty);
|
||||
|
||||
expect(manager.updateScheduled, isTrue);
|
||||
|
@ -2,7 +2,6 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:typed_data';
|
||||
@ -25,9 +24,9 @@ void main() {
|
||||
});
|
||||
|
||||
final RestorationManager manager = RestorationManager();
|
||||
final Future<RestorationBucket> rootBucketFuture = manager.rootBucket;
|
||||
RestorationBucket rootBucket;
|
||||
rootBucketFuture.then((RestorationBucket bucket) {
|
||||
final Future<RestorationBucket?> rootBucketFuture = manager.rootBucket;
|
||||
RestorationBucket? rootBucket;
|
||||
rootBucketFuture.then((RestorationBucket? bucket) {
|
||||
rootBucket = bucket;
|
||||
});
|
||||
expect(rootBucketFuture, isNotNull);
|
||||
@ -48,14 +47,14 @@ void main() {
|
||||
expect(rootBucket, isNotNull);
|
||||
|
||||
// Root bucket contains the expected data.
|
||||
expect(rootBucket.read<int>('value1'), 10);
|
||||
expect(rootBucket.read<String>('value2'), 'Hello');
|
||||
final RestorationBucket child = rootBucket.claimChild('child1', debugOwner: null);
|
||||
expect(rootBucket!.read<int>('value1'), 10);
|
||||
expect(rootBucket!.read<String>('value2'), 'Hello');
|
||||
final RestorationBucket child = rootBucket!.claimChild('child1', debugOwner: null);
|
||||
expect(child.read<int>('another value'), 22);
|
||||
|
||||
// Accessing the root bucket again completes synchronously with same bucket.
|
||||
RestorationBucket synchronousBucket;
|
||||
manager.rootBucket.then((RestorationBucket bucket) {
|
||||
RestorationBucket? synchronousBucket;
|
||||
manager.rootBucket.then((RestorationBucket? bucket) {
|
||||
synchronousBucket = bucket;
|
||||
});
|
||||
expect(synchronousBucket, isNotNull);
|
||||
@ -65,16 +64,15 @@ void main() {
|
||||
testWidgets('root bucket received from engine before retrieval', (WidgetTester tester) async {
|
||||
SystemChannels.restoration.setMethodCallHandler(null);
|
||||
final List<MethodCall> callsToEngine = <MethodCall>[];
|
||||
SystemChannels.restoration.setMockMethodCallHandler((MethodCall call) {
|
||||
SystemChannels.restoration.setMockMethodCallHandler((MethodCall call) async {
|
||||
callsToEngine.add(call);
|
||||
return null;
|
||||
});
|
||||
final RestorationManager manager = RestorationManager();
|
||||
|
||||
await _pushDataFromEngine(_createEncodedRestorationData1());
|
||||
|
||||
RestorationBucket rootBucket;
|
||||
manager.rootBucket.then((RestorationBucket bucket) => rootBucket = bucket);
|
||||
RestorationBucket? rootBucket;
|
||||
manager.rootBucket.then((RestorationBucket? bucket) => rootBucket = bucket);
|
||||
// Root bucket is available synchronously.
|
||||
expect(rootBucket, isNotNull);
|
||||
// Engine was never asked.
|
||||
@ -91,24 +89,24 @@ void main() {
|
||||
});
|
||||
final RestorationManager manager = RestorationManager();
|
||||
|
||||
RestorationBucket rootBucket;
|
||||
manager.rootBucket.then((RestorationBucket bucket) => rootBucket = bucket);
|
||||
RestorationBucket? rootBucket;
|
||||
manager.rootBucket.then((RestorationBucket? bucket) => rootBucket = bucket);
|
||||
expect(rootBucket, isNull);
|
||||
expect(callsToEngine.single.method, 'get');
|
||||
|
||||
await _pushDataFromEngine(_createEncodedRestorationData1());
|
||||
expect(rootBucket, isNotNull);
|
||||
expect(rootBucket.read<int>('value1'), 10);
|
||||
expect(rootBucket!.read<int>('value1'), 10);
|
||||
|
||||
result.complete(_createEncodedRestorationData2());
|
||||
await tester.pump();
|
||||
|
||||
RestorationBucket rootBucket2;
|
||||
manager.rootBucket.then((RestorationBucket bucket) => rootBucket2 = bucket);
|
||||
RestorationBucket? rootBucket2;
|
||||
manager.rootBucket.then((RestorationBucket? bucket) => rootBucket2 = bucket);
|
||||
expect(rootBucket2, isNotNull);
|
||||
expect(rootBucket2, same(rootBucket));
|
||||
expect(rootBucket2.read<int>('value1'), 10);
|
||||
expect(rootBucket2.contains('foo'), isFalse);
|
||||
expect(rootBucket2!.read<int>('value1'), 10);
|
||||
expect(rootBucket2!.contains('foo'), isFalse);
|
||||
});
|
||||
|
||||
testWidgets('root bucket is properly replaced when new data is available', (WidgetTester tester) async {
|
||||
@ -116,21 +114,21 @@ void main() {
|
||||
return _createEncodedRestorationData1();
|
||||
});
|
||||
final RestorationManager manager = RestorationManager();
|
||||
RestorationBucket rootBucket;
|
||||
manager.rootBucket.then((RestorationBucket bucket) {
|
||||
RestorationBucket? rootBucket;
|
||||
manager.rootBucket.then((RestorationBucket? bucket) {
|
||||
rootBucket = bucket;
|
||||
});
|
||||
await tester.pump();
|
||||
expect(rootBucket, isNotNull);
|
||||
expect(rootBucket.read<int>('value1'), 10);
|
||||
final RestorationBucket child = rootBucket.claimChild('child1', debugOwner: null);
|
||||
expect(rootBucket!.read<int>('value1'), 10);
|
||||
final RestorationBucket child = rootBucket!.claimChild('child1', debugOwner: null);
|
||||
expect(child.read<int>('another value'), 22);
|
||||
|
||||
bool rootReplaced = false;
|
||||
RestorationBucket newRoot;
|
||||
RestorationBucket? newRoot;
|
||||
manager.addListener(() {
|
||||
rootReplaced = true;
|
||||
manager.rootBucket.then((RestorationBucket bucket) {
|
||||
manager.rootBucket.then((RestorationBucket? bucket) {
|
||||
newRoot = bucket;
|
||||
});
|
||||
// The new bucket is available synchronously.
|
||||
@ -145,9 +143,9 @@ void main() {
|
||||
|
||||
child.dispose();
|
||||
|
||||
expect(newRoot.read<int>('foo'), 33);
|
||||
expect(newRoot.read<int>('value1'), null);
|
||||
final RestorationBucket newChild = newRoot.claimChild('childFoo', debugOwner: null);
|
||||
expect(newRoot!.read<int>('foo'), 33);
|
||||
expect(newRoot!.read<int>('value1'), null);
|
||||
final RestorationBucket newChild = newRoot!.claimChild('childFoo', debugOwner: null);
|
||||
expect(newChild.read<String>('bar'), 'Hello');
|
||||
});
|
||||
|
||||
@ -162,9 +160,9 @@ void main() {
|
||||
final RestorationManager manager = RestorationManager()..addListener(() {
|
||||
listenerCount++;
|
||||
});
|
||||
RestorationBucket rootBucket;
|
||||
RestorationBucket? rootBucket;
|
||||
bool rootBucketResolved = false;
|
||||
manager.rootBucket.then((RestorationBucket bucket) {
|
||||
manager.rootBucket.then((RestorationBucket? bucket) {
|
||||
rootBucketResolved = true;
|
||||
rootBucket = bucket;
|
||||
});
|
||||
@ -180,7 +178,7 @@ void main() {
|
||||
// Switch to non-null.
|
||||
await _pushDataFromEngine(_createEncodedRestorationData1());
|
||||
expect(listenerCount, 1);
|
||||
manager.rootBucket.then((RestorationBucket bucket) {
|
||||
manager.rootBucket.then((RestorationBucket? bucket) {
|
||||
rootBucket = bucket;
|
||||
});
|
||||
expect(rootBucket, isNotNull);
|
||||
@ -188,7 +186,7 @@ void main() {
|
||||
// Switch to null again.
|
||||
await _pushDataFromEngine(_packageRestorationData(enabled: false));
|
||||
expect(listenerCount, 2);
|
||||
manager.rootBucket.then((RestorationBucket bucket) {
|
||||
manager.rootBucket.then((RestorationBucket? bucket) {
|
||||
rootBucket = bucket;
|
||||
});
|
||||
expect(rootBucket, isNull);
|
||||
@ -203,9 +201,9 @@ void main() {
|
||||
});
|
||||
|
||||
final RestorationManager manager = RestorationManager();
|
||||
final Future<RestorationBucket> rootBucketFuture = manager.rootBucket;
|
||||
RestorationBucket rootBucket;
|
||||
rootBucketFuture.then((RestorationBucket bucket) {
|
||||
final Future<RestorationBucket?> rootBucketFuture = manager.rootBucket;
|
||||
RestorationBucket? rootBucket;
|
||||
rootBucketFuture.then((RestorationBucket? bucket) {
|
||||
rootBucket = bucket;
|
||||
});
|
||||
result.complete(_createEncodedRestorationData1());
|
||||
@ -214,8 +212,8 @@ void main() {
|
||||
callsToEngine.clear();
|
||||
|
||||
// Schedule a frame.
|
||||
SchedulerBinding.instance.ensureVisualUpdate();
|
||||
rootBucket.write('foo', 1);
|
||||
SchedulerBinding.instance!.ensureVisualUpdate();
|
||||
rootBucket!.write('foo', 1);
|
||||
// flushData is no-op because frame is scheduled.
|
||||
manager.flushData();
|
||||
expect(callsToEngine, isEmpty);
|
||||
@ -225,7 +223,7 @@ void main() {
|
||||
callsToEngine.clear();
|
||||
|
||||
// flushData without frame sends data directly.
|
||||
rootBucket.write('foo', 2);
|
||||
rootBucket!.write('foo', 2);
|
||||
manager.flushData();
|
||||
expect(callsToEngine, hasLength(1));
|
||||
});
|
||||
@ -239,40 +237,40 @@ void main() {
|
||||
final TestRestorationManager manager = TestRestorationManager();
|
||||
expect(manager.isReplacing, isFalse);
|
||||
|
||||
RestorationBucket rootBucket;
|
||||
manager.rootBucket.then((RestorationBucket bucket) {
|
||||
RestorationBucket? rootBucket;
|
||||
manager.rootBucket.then((RestorationBucket? bucket) {
|
||||
rootBucket = bucket;
|
||||
});
|
||||
result.complete(_createEncodedRestorationData1());
|
||||
await tester.idle();
|
||||
expect(rootBucket, isNotNull);
|
||||
expect(rootBucket.isReplacing, isFalse);
|
||||
expect(rootBucket!.isReplacing, isFalse);
|
||||
expect(manager.isReplacing, isFalse);
|
||||
tester.binding.scheduleFrame();
|
||||
await tester.pump();
|
||||
expect(manager.isReplacing, isFalse);
|
||||
expect(rootBucket.isReplacing, isFalse);
|
||||
expect(rootBucket!.isReplacing, isFalse);
|
||||
|
||||
manager.receiveDataFromEngine(enabled: true, data: null);
|
||||
RestorationBucket rootBucket2;
|
||||
manager.rootBucket.then((RestorationBucket bucket) {
|
||||
RestorationBucket? rootBucket2;
|
||||
manager.rootBucket.then((RestorationBucket? bucket) {
|
||||
rootBucket2 = bucket;
|
||||
});
|
||||
expect(rootBucket2, isNotNull);
|
||||
expect(rootBucket2, isNot(same(rootBucket)));
|
||||
expect(rootBucket2!, isNot(same(rootBucket)));
|
||||
expect(manager.isReplacing, isTrue);
|
||||
expect(rootBucket2.isReplacing, isTrue);
|
||||
expect(rootBucket2!.isReplacing, isTrue);
|
||||
await tester.idle();
|
||||
expect(manager.isReplacing, isTrue);
|
||||
expect(rootBucket2.isReplacing, isTrue);
|
||||
expect(rootBucket2!.isReplacing, isTrue);
|
||||
tester.binding.scheduleFrame();
|
||||
await tester.pump();
|
||||
expect(manager.isReplacing, isFalse);
|
||||
expect(rootBucket2.isReplacing, isFalse);
|
||||
expect(rootBucket2!.isReplacing, isFalse);
|
||||
|
||||
manager.receiveDataFromEngine(enabled: false, data: null);
|
||||
RestorationBucket rootBucket3;
|
||||
manager.rootBucket.then((RestorationBucket bucket) {
|
||||
RestorationBucket? rootBucket3;
|
||||
manager.rootBucket.then((RestorationBucket? bucket) {
|
||||
rootBucket3 = bucket;
|
||||
});
|
||||
expect(rootBucket3, isNull);
|
||||
@ -307,7 +305,7 @@ void main() {
|
||||
}
|
||||
|
||||
Future<void> _pushDataFromEngine(Map<dynamic, dynamic> data) async {
|
||||
await ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage(
|
||||
await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage(
|
||||
'flutter/restoration',
|
||||
const StandardMethodCodec().encodeMethodCall(MethodCall('push', data)),
|
||||
(_) { },
|
||||
@ -347,16 +345,16 @@ Map<dynamic, dynamic> _createEncodedRestorationData2() {
|
||||
return _packageRestorationData(data: data);
|
||||
}
|
||||
|
||||
Map<dynamic, dynamic> _packageRestorationData({bool enabled = true, Map<dynamic, dynamic> data}) {
|
||||
final ByteData encoded = const StandardMessageCodec().encodeMessage(data);
|
||||
Map<dynamic, dynamic> _packageRestorationData({bool enabled = true, Map<dynamic, dynamic>? data}) {
|
||||
final ByteData? encoded = const StandardMessageCodec().encodeMessage(data);
|
||||
return <dynamic, dynamic>{
|
||||
'enabled': enabled,
|
||||
'data': encoded == null ? null : encoded.buffer.asUint8List(encoded.offsetInBytes, encoded.lengthInBytes)
|
||||
'data': encoded?.buffer.asUint8List(encoded.offsetInBytes, encoded.lengthInBytes),
|
||||
};
|
||||
}
|
||||
|
||||
class TestRestorationManager extends RestorationManager {
|
||||
void receiveDataFromEngine({@required bool enabled, @required Uint8List data}) {
|
||||
void receiveDataFromEngine({required bool enabled, required Uint8List? data}) {
|
||||
handleRestorationUpdateFromEngine(enabled: enabled, data: data);
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,6 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'dart:typed_data';
|
||||
|
||||
@ -61,11 +60,10 @@ void main() {
|
||||
});
|
||||
|
||||
test('setApplicationSwitcherDescription missing plugin', () async {
|
||||
final List<ByteData> log = <ByteData>[];
|
||||
final List<ByteData?> log = <ByteData>[];
|
||||
|
||||
ServicesBinding.instance.defaultBinaryMessenger.setMockMessageHandler('flutter/platform', (ByteData message) {
|
||||
ServicesBinding.instance!.defaultBinaryMessenger.setMockMessageHandler('flutter/platform', (ByteData? message) async {
|
||||
log.add(message);
|
||||
return null;
|
||||
});
|
||||
|
||||
await SystemChrome.setApplicationSwitcherDescription(
|
||||
|
@ -2,7 +2,6 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
@ -2,7 +2,6 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
@ -2,27 +2,25 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
void main() {
|
||||
TextEditingValue testOldValue;
|
||||
TextEditingValue testNewValue;
|
||||
TextEditingValue testOldValue = TextEditingValue.empty;
|
||||
TextEditingValue testNewValue = TextEditingValue.empty;
|
||||
|
||||
test('withFunction wraps formatting function', () {
|
||||
testOldValue = const TextEditingValue();
|
||||
testNewValue = const TextEditingValue();
|
||||
|
||||
TextEditingValue calledOldValue;
|
||||
TextEditingValue calledNewValue;
|
||||
late TextEditingValue calledOldValue;
|
||||
late TextEditingValue calledNewValue;
|
||||
|
||||
final TextInputFormatter formatterUnderTest = TextInputFormatter.withFunction(
|
||||
(TextEditingValue oldValue, TextEditingValue newValue) {
|
||||
calledOldValue = oldValue;
|
||||
calledNewValue = newValue;
|
||||
return null;
|
||||
return TextEditingValue.empty;
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -2,7 +2,6 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'dart:convert' show utf8;
|
||||
import 'dart:convert' show jsonDecode;
|
||||
@ -15,7 +14,7 @@ void main() {
|
||||
TestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
group('TextInput message channels', () {
|
||||
FakeTextChannel fakeTextChannel;
|
||||
late FakeTextChannel fakeTextChannel;
|
||||
|
||||
setUp(() {
|
||||
fakeTextChannel = FakeTextChannel((MethodCall call) async {});
|
||||
@ -34,7 +33,7 @@ void main() {
|
||||
MethodCall('TextInput.setClient', <dynamic>[1, client.configuration.toJson()]),
|
||||
]);
|
||||
|
||||
fakeTextChannel.incoming(const MethodCall('TextInputClient.requestExistingInputState', null));
|
||||
fakeTextChannel.incoming!(const MethodCall('TextInputClient.requestExistingInputState', null));
|
||||
|
||||
expect(fakeTextChannel.outgoingCalls.length, 3);
|
||||
fakeTextChannel.validateOutgoingMethodCalls(<MethodCall>[
|
||||
@ -47,20 +46,32 @@ void main() {
|
||||
});
|
||||
|
||||
test('text input client handler responds to reattach with setClient (null TextEditingValue)', () async {
|
||||
final FakeTextInputClient client = FakeTextInputClient(null);
|
||||
final FakeTextInputClient client = FakeTextInputClient(TextEditingValue.empty);
|
||||
TextInput.attach(client, client.configuration);
|
||||
fakeTextChannel.validateOutgoingMethodCalls(<MethodCall>[
|
||||
MethodCall('TextInput.setClient', <dynamic>[1, client.configuration.toJson()]),
|
||||
]);
|
||||
|
||||
fakeTextChannel.incoming(const MethodCall('TextInputClient.requestExistingInputState', null));
|
||||
fakeTextChannel.incoming!(const MethodCall('TextInputClient.requestExistingInputState', null));
|
||||
|
||||
expect(fakeTextChannel.outgoingCalls.length, 2);
|
||||
expect(fakeTextChannel.outgoingCalls.length, 3);
|
||||
fakeTextChannel.validateOutgoingMethodCalls(<MethodCall>[
|
||||
// From original attach
|
||||
MethodCall('TextInput.setClient', <dynamic>[1, client.configuration.toJson()]),
|
||||
// From requestExistingInputState
|
||||
// From original attach
|
||||
MethodCall('TextInput.setClient', <dynamic>[1, client.configuration.toJson()]),
|
||||
// From requestExistingInputState
|
||||
const MethodCall(
|
||||
'TextInput.setEditingState',
|
||||
<String, dynamic>{
|
||||
'text': '',
|
||||
'selectionBase': -1,
|
||||
'selectionExtent': -1,
|
||||
'selectionAffinity': 'TextAffinity.downstream',
|
||||
'selectionIsDirectional': false,
|
||||
'composingBase': -1,
|
||||
'composingExtent': -1,
|
||||
}),
|
||||
]);
|
||||
});
|
||||
});
|
||||
@ -162,14 +173,14 @@ void main() {
|
||||
expect(client.latestMethodCall, isEmpty);
|
||||
|
||||
// Send onConnectionClosed message.
|
||||
final ByteData messageBytes = const JSONMessageCodec().encodeMessage(<String, dynamic>{
|
||||
final ByteData? messageBytes = const JSONMessageCodec().encodeMessage(<String, dynamic>{
|
||||
'args': <dynamic>[1],
|
||||
'method': 'TextInputClient.onConnectionClosed',
|
||||
});
|
||||
await ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage(
|
||||
await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage(
|
||||
'flutter/textinput',
|
||||
messageBytes,
|
||||
(ByteData _) {},
|
||||
(ByteData? _) {},
|
||||
);
|
||||
|
||||
expect(client.latestMethodCall, 'connectionClosed');
|
||||
@ -177,14 +188,14 @@ void main() {
|
||||
|
||||
test('TextInputClient performPrivateCommand method is called', () async {
|
||||
// Assemble a TextInputConnection so we can verify its change in state.
|
||||
final FakeTextInputClient client = FakeTextInputClient(null);
|
||||
final FakeTextInputClient client = FakeTextInputClient(TextEditingValue.empty);
|
||||
const TextInputConfiguration configuration = TextInputConfiguration();
|
||||
TextInput.attach(client, configuration);
|
||||
|
||||
expect(client.latestMethodCall, isEmpty);
|
||||
|
||||
// Send performPrivateCommand message.
|
||||
final ByteData messageBytes = const JSONMessageCodec().encodeMessage(<String, dynamic>{
|
||||
final ByteData? messageBytes = const JSONMessageCodec().encodeMessage(<String, dynamic>{
|
||||
'args': <dynamic>[
|
||||
1,
|
||||
jsonDecode(
|
||||
@ -192,10 +203,10 @@ void main() {
|
||||
],
|
||||
'method': 'TextInputClient.performPrivateCommand',
|
||||
});
|
||||
await ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage(
|
||||
await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage(
|
||||
'flutter/textinput',
|
||||
messageBytes,
|
||||
(ByteData _) {},
|
||||
(ByteData? _) {},
|
||||
);
|
||||
|
||||
expect(client.latestMethodCall, 'performPrivateCommand');
|
||||
@ -204,14 +215,14 @@ void main() {
|
||||
test('TextInputClient performPrivateCommand method is called with float',
|
||||
() async {
|
||||
// Assemble a TextInputConnection so we can verify its change in state.
|
||||
final FakeTextInputClient client = FakeTextInputClient(null);
|
||||
final FakeTextInputClient client = FakeTextInputClient(const TextEditingValue());
|
||||
const TextInputConfiguration configuration = TextInputConfiguration();
|
||||
TextInput.attach(client, configuration);
|
||||
|
||||
expect(client.latestMethodCall, isEmpty);
|
||||
|
||||
// Send performPrivateCommand message.
|
||||
final ByteData messageBytes = const JSONMessageCodec().encodeMessage(<String, dynamic>{
|
||||
final ByteData? messageBytes = const JSONMessageCodec().encodeMessage(<String, dynamic>{
|
||||
'args': <dynamic>[
|
||||
1,
|
||||
jsonDecode(
|
||||
@ -219,10 +230,10 @@ void main() {
|
||||
],
|
||||
'method': 'TextInputClient.performPrivateCommand',
|
||||
});
|
||||
await ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage(
|
||||
await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage(
|
||||
'flutter/textinput',
|
||||
messageBytes,
|
||||
(ByteData _) {},
|
||||
(ByteData? _) {},
|
||||
);
|
||||
|
||||
expect(client.latestMethodCall, 'performPrivateCommand');
|
||||
@ -232,14 +243,14 @@ void main() {
|
||||
'TextInputClient performPrivateCommand method is called with CharSequence array',
|
||||
() async {
|
||||
// Assemble a TextInputConnection so we can verify its change in state.
|
||||
final FakeTextInputClient client = FakeTextInputClient(null);
|
||||
final FakeTextInputClient client = FakeTextInputClient(const TextEditingValue());
|
||||
const TextInputConfiguration configuration = TextInputConfiguration();
|
||||
TextInput.attach(client, configuration);
|
||||
|
||||
expect(client.latestMethodCall, isEmpty);
|
||||
|
||||
// Send performPrivateCommand message.
|
||||
final ByteData messageBytes = const JSONMessageCodec().encodeMessage(<String, dynamic>{
|
||||
final ByteData? messageBytes = const JSONMessageCodec().encodeMessage(<String, dynamic>{
|
||||
'args': <dynamic>[
|
||||
1,
|
||||
jsonDecode(
|
||||
@ -247,10 +258,10 @@ void main() {
|
||||
],
|
||||
'method': 'TextInputClient.performPrivateCommand',
|
||||
});
|
||||
await ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage(
|
||||
await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage(
|
||||
'flutter/textinput',
|
||||
messageBytes,
|
||||
(ByteData _) {},
|
||||
(ByteData? _) {},
|
||||
);
|
||||
|
||||
expect(client.latestMethodCall, 'performPrivateCommand');
|
||||
@ -260,14 +271,14 @@ void main() {
|
||||
'TextInputClient performPrivateCommand method is called with CharSequence',
|
||||
() async {
|
||||
// Assemble a TextInputConnection so we can verify its change in state.
|
||||
final FakeTextInputClient client = FakeTextInputClient(null);
|
||||
final FakeTextInputClient client = FakeTextInputClient(const TextEditingValue());
|
||||
const TextInputConfiguration configuration = TextInputConfiguration();
|
||||
TextInput.attach(client, configuration);
|
||||
|
||||
expect(client.latestMethodCall, isEmpty);
|
||||
|
||||
// Send performPrivateCommand message.
|
||||
final ByteData messageBytes =
|
||||
final ByteData? messageBytes =
|
||||
const JSONMessageCodec().encodeMessage(<String, dynamic>{
|
||||
'args': <dynamic>[
|
||||
1,
|
||||
@ -276,10 +287,10 @@ void main() {
|
||||
],
|
||||
'method': 'TextInputClient.performPrivateCommand',
|
||||
});
|
||||
await ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage(
|
||||
await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage(
|
||||
'flutter/textinput',
|
||||
messageBytes,
|
||||
(ByteData _) {},
|
||||
(ByteData? _) {},
|
||||
);
|
||||
|
||||
expect(client.latestMethodCall, 'performPrivateCommand');
|
||||
@ -289,14 +300,14 @@ void main() {
|
||||
'TextInputClient performPrivateCommand method is called with float array',
|
||||
() async {
|
||||
// Assemble a TextInputConnection so we can verify its change in state.
|
||||
final FakeTextInputClient client = FakeTextInputClient(null);
|
||||
final FakeTextInputClient client = FakeTextInputClient(const TextEditingValue());
|
||||
const TextInputConfiguration configuration = TextInputConfiguration();
|
||||
TextInput.attach(client, configuration);
|
||||
|
||||
expect(client.latestMethodCall, isEmpty);
|
||||
|
||||
// Send performPrivateCommand message.
|
||||
final ByteData messageBytes =
|
||||
final ByteData? messageBytes =
|
||||
const JSONMessageCodec().encodeMessage(<String, dynamic>{
|
||||
'args': <dynamic>[
|
||||
1,
|
||||
@ -305,10 +316,10 @@ void main() {
|
||||
],
|
||||
'method': 'TextInputClient.performPrivateCommand',
|
||||
});
|
||||
await ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage(
|
||||
await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage(
|
||||
'flutter/textinput',
|
||||
messageBytes,
|
||||
(ByteData _) {},
|
||||
(ByteData? _) {},
|
||||
);
|
||||
|
||||
expect(client.latestMethodCall, 'performPrivateCommand');
|
||||
@ -317,22 +328,22 @@ void main() {
|
||||
test('TextInputClient showAutocorrectionPromptRect method is called',
|
||||
() async {
|
||||
// Assemble a TextInputConnection so we can verify its change in state.
|
||||
final FakeTextInputClient client = FakeTextInputClient(null);
|
||||
final FakeTextInputClient client = FakeTextInputClient(const TextEditingValue());
|
||||
const TextInputConfiguration configuration = TextInputConfiguration();
|
||||
TextInput.attach(client, configuration);
|
||||
|
||||
expect(client.latestMethodCall, isEmpty);
|
||||
|
||||
// Send onConnectionClosed message.
|
||||
final ByteData messageBytes =
|
||||
final ByteData? messageBytes =
|
||||
const JSONMessageCodec().encodeMessage(<String, dynamic>{
|
||||
'args': <dynamic>[1, 0, 1],
|
||||
'method': 'TextInputClient.showAutocorrectionPromptRect',
|
||||
});
|
||||
await ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage(
|
||||
await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage(
|
||||
'flutter/textinput',
|
||||
messageBytes,
|
||||
(ByteData _) {},
|
||||
(ByteData? _) {},
|
||||
);
|
||||
|
||||
expect(client.latestMethodCall, 'showAutocorrectionPromptRect');
|
||||
@ -376,7 +387,7 @@ class FakeTextInputClient implements TextInputClient {
|
||||
TextEditingValue currentTextEditingValue;
|
||||
|
||||
@override
|
||||
AutofillScope get currentAutofillScope => null;
|
||||
AutofillScope? get currentAutofillScope => null;
|
||||
|
||||
@override
|
||||
void performAction(TextInputAction action) {
|
||||
@ -415,7 +426,7 @@ class FakeTextChannel implements MethodChannel {
|
||||
FakeTextChannel(this.outgoing) : assert(outgoing != null);
|
||||
|
||||
Future<dynamic> Function(MethodCall) outgoing;
|
||||
Future<void> Function(MethodCall) incoming;
|
||||
Future<void> Function(MethodCall)? incoming;
|
||||
|
||||
List<MethodCall> outgoingCalls = <MethodCall>[];
|
||||
|
||||
@ -442,19 +453,17 @@ class FakeTextChannel implements MethodChannel {
|
||||
String get name => 'flutter/textinput';
|
||||
|
||||
@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();
|
||||
bool checkMethodCallHandler(Future<void> Function(MethodCall call)? handler) => throw UnimplementedError();
|
||||
|
||||
|
||||
@override
|
||||
void setMockMethodCallHandler(Future<void> Function(MethodCall call) handler) => throw UnimplementedError();
|
||||
void setMockMethodCallHandler(Future<void> Function(MethodCall call)? handler) => throw UnimplementedError();
|
||||
|
||||
@override
|
||||
bool checkMockMethodCallHandler(Future<void> Function(MethodCall call) handler) => throw UnimplementedError();
|
||||
bool checkMockMethodCallHandler(Future<void> Function(MethodCall call)? handler) => throw UnimplementedError();
|
||||
|
||||
void validateOutgoingMethodCalls(List<MethodCall> calls) {
|
||||
expect(outgoingCalls.length, calls.length);
|
||||
@ -468,8 +477,8 @@ class FakeTextChannel implements MethodChannel {
|
||||
if (outgoingString != expectedString) {
|
||||
print(
|
||||
'Index $i did not match:\n'
|
||||
' actual: ${outgoingCalls[i]}\n'
|
||||
' expected: ${calls[i]}');
|
||||
' actual: $outgoingString\n'
|
||||
' expected: $expectedString');
|
||||
hasError = true;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user