blob: df39a632a8e9a03f7a711309d42e22bb42e6a556 [file]
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
void main() {
final TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized();
group('Undo Interactions', () {
test('UndoManagerClient handleUndo', () async {
// Assemble an UndoManagerClient so we can verify its change in state.
final client = _FakeUndoManagerClient();
UndoManager.client = client;
expect(client.latestMethodCall, isEmpty);
// Send handleUndo message with "undo" as the direction.
ByteData? messageBytes = const JSONMessageCodec().encodeMessage(<String, dynamic>{
'args': <dynamic>['undo'],
'method': 'UndoManagerClient.handleUndo',
});
await binding.defaultBinaryMessenger.handlePlatformMessage(
'flutter/undomanager',
messageBytes,
null,
);
expect(client.latestMethodCall, 'handlePlatformUndo(${UndoDirection.undo})');
// Send handleUndo message with "undo" as the direction.
messageBytes = const JSONMessageCodec().encodeMessage(<String, dynamic>{
'args': <dynamic>['redo'],
'method': 'UndoManagerClient.handleUndo',
});
await binding.defaultBinaryMessenger.handlePlatformMessage(
'flutter/undomanager',
messageBytes,
(ByteData? _) {},
);
expect(client.latestMethodCall, 'handlePlatformUndo(${UndoDirection.redo})');
});
test('UndoManager.setUndoState reports error when channel fails', () async {
final FlutterExceptionHandler? oldOnError = FlutterError.onError;
final errors = <FlutterErrorDetails>[];
// Use a Completer to signal when the error has been caught.
final errorReceived = Completer<void>();
FlutterError.onError = (FlutterErrorDetails details) {
errors.add(details);
if (!errorReceived.isCompleted) {
errorReceived.complete();
}
};
try {
final log = <MethodCall>[];
const channel = MethodChannel('flutter/undomanager');
UndoManager.setChannel(channel);
channel.setMockMethodCallHandler((MethodCall methodCall) async {
log.add(methodCall);
throw Exception('Channel failed');
});
UndoManager.setUndoState(canUndo: true, canRedo: true);
// Wait specifically for the error handler to fire.
// Set a timeout so the test doesn't hang forever if it fails.
await errorReceived.future.timeout(const Duration(seconds: 5));
expect(errors, hasLength(1));
expect(errors.single.exception, isA<Exception>());
expect(errors.single.exception.toString(), contains('Channel failed'));
expect(
errors.single.context.toString(),
contains('while sending the UndoManager.setUndoState event'),
);
expect(log, hasLength(1));
expect(log.single.method, 'UndoManager.setUndoState');
} finally {
FlutterError.onError = oldOnError;
UndoManager.setChannel(SystemChannels.undoManager);
}
});
});
}
class _FakeUndoManagerClient with UndoManagerClient {
String latestMethodCall = '';
@override
void undo() {}
@override
void redo() {}
@override
bool get canUndo => false;
@override
bool get canRedo => false;
@override
void handlePlatformUndo(UndoDirection direction) {
latestMethodCall = 'handlePlatformUndo($direction)';
}
}