diff --git a/lib/src/golden_test.dart b/lib/src/golden_test.dart index ed8eb75..f62ed86 100644 --- a/lib/src/golden_test.dart +++ b/lib/src/golden_test.dart @@ -1,4 +1,5 @@ import 'dart:convert'; +import 'dart:io'; import 'dart:ui' as ui; import 'package:alchemist/alchemist.dart'; @@ -10,6 +11,7 @@ import 'package:flutter/rendering.dart'; import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:meta/meta.dart'; +import 'package:yaml/yaml.dart'; /// Default golden test runner which uses the flutter test framework. const defaultGoldenTestRunner = FlutterGoldenTestRunner(); @@ -37,26 +39,58 @@ Future _setUpGoldenTests() async { @visibleForTesting Future loadFonts() async { final bundle = rootBundle; + final packageName = _getPackageName(); + final fontManifestString = await bundle.loadString('FontManifest.json'); final fontManifest = (json.decode(fontManifestString) as List) .map((dynamic x) => x as Map); for (final entry in fontManifest) { - final family = - (entry['family'] as String).stripFontFamilyAlchemistPackageName(); + final baseFamily = entry['family'] as String; + final family = baseFamily.stripFontFamilyAlchemistPackageName(); final fontAssets = [ for (final fontAssetEntry in entry['fonts'] as List) (fontAssetEntry as Map)['asset'] as String, ]; - final loader = FontLoader(family); - for (final fontAsset in fontAssets) { - loader.addFont(bundle.load(fontAsset)); + await _loadFontFamily(family, fontAssets); + + // Check if the font is a custom user-specified font. + // `MaterialIcons` is a special case, added by specifying + // `flutter` -> `uses-material-design: true` in `pubspec.yaml`. + final isCustomFont = + !baseFamily.startsWith('packages/') && family != 'MaterialIcons'; + + // Register same-package custom fonts under an alias. + if (isCustomFont && packageName != null) { + final aliasFamily = 'packages/$packageName/$baseFamily'; + await _loadFontFamily(aliasFamily, fontAssets); } + } +} - await loader.load(); +/// Returns the name of the package from which the golden test is being run. +/// `null` if the package name cannot be determined. +String? _getPackageName() { + final pubspecFile = File('pubspec.yaml'); + if (!pubspecFile.existsSync()) { + return null; } + + final pubspec = loadYaml(pubspecFile.readAsStringSync()) as YamlMap; + return pubspec['name'] as String?; +} + +/// Loads fonts from a font family for use in golden tests. +Future _loadFontFamily(String family, List fontAssets) async { + final bundle = rootBundle; + final loader = FontLoader(family); + for (final fontAsset in fontAssets) { + loader.addFont(bundle.load(fontAsset)); + } + + await loader.load(); } /// Performs a Flutter widget test that compares against golden image. diff --git a/pubspec.yaml b/pubspec.yaml index eb8a04e..bb56d2a 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -16,6 +16,7 @@ dependencies: flutter_test: sdk: flutter meta: ^1.7.0 + yaml: ^3.1.2 dev_dependencies: mocktail: ^0.3.0 diff --git a/test/smoke_tests/text_package_smoke_test.dart b/test/smoke_tests/text_package_smoke_test.dart new file mode 100644 index 0000000..cf4ef6d --- /dev/null +++ b/test/smoke_tests/text_package_smoke_test.dart @@ -0,0 +1,30 @@ +import 'package:alchemist/src/golden_test.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + group('smoke test', () { + goldenTest( + 'succeeds without a package name', + fileName: 'text_package_smoke_test_no_package', + builder: () => const Text( + 'Hello, world!', + style: TextStyle( + fontFamily: 'Roboto', + ), + ), + ); + + goldenTest( + 'succeeds with a package name', + fileName: 'text_package_smoke_test_specified', + builder: () => const Text( + 'Hello, world!', + style: TextStyle( + fontFamily: 'Roboto', + package: 'alchemist', + ), + ), + ); + }); +}