matchAsync method

  1. @override
Future<String?> matchAsync(
  1. dynamic item
)

Returns null if this matches item, or a String description of the failure if it doesn't match.

This can return a Future or a synchronous value. If it returns a Future, neither expect nor the test will complete until that Future completes.

If this returns a String synchronously, expect will synchronously throw a TestFailure and matches will synchronously return false.

Implementation

@override
Future<String?> matchAsync(dynamic item) async {
  final Uri testNameUri = goldenFileComparator.getTestUri(key, version);

  Uint8List? buffer;
  if (item is Future<List<int>?>) {
    final List<int>? bytes = await item;
    buffer = bytes == null ? null : Uint8List.fromList(bytes);
  } else if (item is List<int>) {
    buffer = Uint8List.fromList(item);
  }
  if (buffer != null) {
    if (autoUpdateGoldenFiles) {
      await goldenFileComparator.update(testNameUri, buffer);
      return null;
    }
    try {
      final bool success = await goldenFileComparator.compare(buffer, testNameUri);
      return success ? null : 'does not match';
    } on TestFailure catch (ex) {
      return ex.message;
    }
  }
  Future<ui.Image?> imageFuture;
  final bool disposeImage; // set to true if the matcher created and owns the image and must therefore dispose it.
  if (item is Future<ui.Image?>) {
    imageFuture = item;
    disposeImage = false;
  } else if (item is ui.Image) {
    imageFuture = Future<ui.Image>.value(item);
    disposeImage = false;
  } else if (item is Finder) {
    final Iterable<Element> elements = item.evaluate();
    if (elements.isEmpty) {
      return 'could not be rendered because no widget was found';
    } else if (elements.length > 1) {
      return 'matched too many widgets';
    }
    imageFuture = captureImage(elements.single);
    disposeImage = true;
  } else {
    throw AssertionError('must provide a Finder, Image, Future<Image>, List<int>, or Future<List<int>>');
  }

  final TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.instance;
  return binding.runAsync<String?>(() async {
    final ui.Image? image = await imageFuture;
    if (image == null) {
      throw AssertionError('Future<Image> completed to null');
    }
    try {
      final ByteData? bytes = await image.toByteData(format: ui.ImageByteFormat.png);
      if (bytes == null) {
        return 'could not encode screenshot.';
      }
      if (autoUpdateGoldenFiles) {
        await goldenFileComparator.update(testNameUri, bytes.buffer.asUint8List());
        return null;
      }
      try {
        final bool success = await goldenFileComparator.compare(bytes.buffer.asUint8List(), testNameUri);
        return success ? null : 'does not match';
      } on TestFailure catch (ex) {
        return ex.message;
      }
    } finally {
      if (disposeImage) {
        image.dispose();
      }
    }
  });
}