blob: 8df49dcac1065ed45f1a31be63101adb0bc958a9 [file] [log] [blame]
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:async';
import 'dart:typed_data';
import 'package:quiver/testing/async.dart';
import 'package:ui/src/engine.dart' hide window;
import 'package:ui/ui.dart';
/// Encapsulates the info of a platform message that was intercepted by
/// [PlatformMessagesSpy].
class PlatformMessage {
PlatformMessage(, this.methodCall);
/// The name of the channel on which the message was sent.
final String channel;
/// The [MethodCall] instance that was sent in the platform message.
final MethodCall methodCall;
/// Shorthand for getting the name of the method call.
String get methodName => methodCall.method;
/// Shorthand for getting the arguments of the method call.
dynamic get methodArguments => methodCall.arguments;
/// Intercepts platform messages sent from the engine to the framework.
/// It holds all intercepted platform messages in a [messages] list that can
/// be inspected in tests.
class PlatformMessagesSpy {
PlatformMessageCallback? _callback;
PlatformMessageCallback? _backup;
bool get _isActive => _callback != null;
/// List of intercepted messages since the last [setUp] call.
final List<PlatformMessage> messages = <PlatformMessage>[];
/// Start spying on platform messages.
/// This is typically called inside a test's `setUp` callback.
void setUp() {
_callback = (String channel, ByteData? data,
PlatformMessageResponseCallback? callback) {
const JSONMethodCodec().decodeMethodCall(data),
_backup = window.onPlatformMessage;
window.onPlatformMessage = _callback;
/// Stop spying on platform messages and clear all intercepted messages.
/// Make sure this is called after each test that uses [PlatformMessagesSpy].
void tearDown() {
// Make sure [window.onPlatformMessage] wasn't tampered with.
assert(window.onPlatformMessage == _callback);
_callback = null;
window.onPlatformMessage = _backup;
/// Runs code in a [FakeAsync] zone and spies on what's going on in it.
class ZoneSpy {
final FakeAsync fakeAsync = FakeAsync();
final List<String> printLog = <String>[];
dynamic run(dynamic Function() function) {
final ZoneSpecification printInterceptor = ZoneSpecification(
print: (Zone self, ZoneDelegate parent, Zone zone, String line) {
return Zone.current.fork(specification: printInterceptor).run<dynamic>(() {
return self) {
return function();