// Author: fruit.com.cn // 为界面视觉复核加载项目字体并导出测试渲染图。 import 'dart:io'; import 'dart:ui' as ui; import 'package:flutter/rendering.dart'; import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; const double _capturePixelRatio = 3; /// 为可选截图使用实际字体,不影响普通测试执行。 Future loadCaptureFonts(WidgetTester tester) async { await tester.runAsync(() async { final fonts = { 'Outfit': [ 'Outfit-Regular.ttf', 'Outfit-SemiBold.ttf', 'Outfit-Bold.ttf', ], 'PlusJakartaSans': [ 'PlusJakartaSans-Regular.ttf', 'PlusJakartaSans-Medium.ttf', 'PlusJakartaSans-SemiBold.ttf', 'PlusJakartaSans-Bold.ttf', ], // 测试默认字体仅作占位,截图使用项目正文字体替换。 'Ahem': ['PlusJakartaSans-Regular.ttf'], }; for (final family in fonts.entries) { final loader = FontLoader(family.key); for (final asset in family.value) { loader.addFont(rootBundle.load('assets/fonts/$asset')); } await loader.load(); } final icons = FontLoader('MaterialIcons'); icons.addFont(rootBundle.load('fonts/MaterialIcons-Regular.otf')); await icons.load(); }); } /// 导出指定边界的渲染结果,图片为测试产物而非界面资源。 Future saveWidgetCapture( WidgetTester tester, Key boundaryKey, String path, ) async { final boundary = tester.renderObject( find.byKey(boundaryKey), ); await tester.runAsync(() async { final image = await boundary.toImage(pixelRatio: _capturePixelRatio); final bytes = await image.toByteData(format: ui.ImageByteFormat.png); if (bytes == null) throw StateError('Screenshot encoding failed'); await File(path).writeAsBytes(bytes.buffer.asUint8List()); image.dispose(); }); }