// Copyright 2014 The Flutter Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. import 'dart:async'; import 'dart:convert' show jsonEncode; import 'dart:developer' as developer; import 'dart:ui' as ui; import 'package:flutter/widgets.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:vm_service/vm_service.dart'; import 'package:vm_service/vm_service_io.dart'; void main() { LiveTestWidgetsFlutterBinding.ensureInitialized(); late VmService vmService; late LiveTestWidgetsFlutterBinding binding; setUpAll(() async { final developer.ServiceProtocolInfo info = await developer.Service.getInfo(); if (info.serverUri == null) { fail('This test _must_ be run with --enable-vmservice.'); } vmService = await vmServiceConnectUri('ws://localhost:${info.serverUri!.port}${info.serverUri!.path}ws'); await vmService.streamListen(EventStreams.kExtension); // Initialize bindings binding = LiveTestWidgetsFlutterBinding.instance; binding.framePolicy = LiveTestWidgetsFlutterBindingFramePolicy.fullyLive; binding.attachRootWidget(const SizedBox.expand()); expect(binding.framesEnabled, true); // Pump two frames to make sure we clear out any inter-frame comparisons. await binding.endOfFrame; await binding.endOfFrame; }); tearDownAll(() async { await vmService.dispose(); }); test('Image painting events - deduplicates across frames', () async { final Completer<Event> completer = Completer<Event>(); vmService .onExtensionEvent .firstWhere((Event event) => event.extensionKind == 'Flutter.ImageSizesForFrame') .then(completer.complete); final ui.Image image = await createTestImage(width: 300, height: 300); final TestCanvas canvas = TestCanvas(); paintImage( canvas: canvas, rect: const Rect.fromLTWH(50.0, 75.0, 200.0, 100.0), image: image, debugImageLabel: 'test.png', ); // Make sure that we don't report an identical image size info if we // redraw in the next frame. await binding.endOfFrame; paintImage( canvas: canvas, rect: const Rect.fromLTWH(50.0, 75.0, 200.0, 100.0), image: image, debugImageLabel: 'test.png', ); await binding.endOfFrame; final Event event = await completer.future; expect(event.extensionKind, 'Flutter.ImageSizesForFrame'); expect( jsonEncode(event.extensionData!.data), contains('"test.png":{"source":"test.png","displaySize":{"width":600.0,"height":300.0},"imageSize":{"width":300.0,"height":300.0},"displaySizeInBytes":960000,"decodedSizeInBytes":480000}'), ); }, skip: isBrowser); // [intended] uses dart:isolate and io. test('Image painting events - deduplicates across frames', () async { final Completer<Event> completer = Completer<Event>(); vmService .onExtensionEvent .firstWhere((Event event) => event.extensionKind == 'Flutter.ImageSizesForFrame') .then(completer.complete); final ui.Image image = await createTestImage(width: 300, height: 300); final TestCanvas canvas = TestCanvas(); paintImage( canvas: canvas, rect: const Rect.fromLTWH(50.0, 75.0, 200.0, 100.0), image: image, debugImageLabel: 'test.png', ); paintImage( canvas: canvas, rect: const Rect.fromLTWH(50.0, 75.0, 300.0, 300.0), image: image, debugImageLabel: 'test.png', ); await binding.endOfFrame; final Event event = await completer.future; expect(event.extensionKind, 'Flutter.ImageSizesForFrame'); expect( jsonEncode(event.extensionData!.data), contains('"test.png":{"source":"test.png","displaySize":{"width":900.0,"height":900.0},"imageSize":{"width":300.0,"height":300.0},"displaySizeInBytes":4320000,"decodedSizeInBytes":480000}'), ); }, skip: isBrowser); // [intended] uses dart:isolate and io. } class TestCanvas implements Canvas { @override void noSuchMethod(Invocation invocation) {} }