|
5 | 5 | /// license that can be found in the LICENSE file or at |
6 | 6 | /// https://opensource.org/licenses/BSD-3-Clause |
7 | 7 | /// *************************************************** |
8 | | -import 'dart:io'; |
9 | | -import 'dart:typed_data'; |
| 8 | +
|
| 9 | +import 'dart:convert'; |
10 | 10 | import 'package:flutter/services.dart'; |
11 | | -import 'package:meta/meta.dart'; |
| 11 | +import 'package:flutter_test/flutter_test.dart'; |
12 | 12 |
|
13 | 13 | ///By default, flutter test only uses a single "test" font called Ahem. |
14 | 14 | /// |
15 | 15 | ///This font is designed to show black spaces for every character and icon. This obviously makes goldens much less valuable. |
16 | 16 | /// |
17 | | -///To make the goldens more useful, we have a utility to dynamically inject additional fonts into the flutter test engine so that we can get more human viewable output. |
18 | | -/// Path to your folder with fonts [from] in required |
19 | | -Future<void> loadAppFonts({@required String from}) async { |
20 | | - if (_hasLoaded) { |
21 | | - print('skipping fonts'); |
22 | | - return; |
23 | | - } |
| 17 | +///To make the goldens more useful, we will automatically load any fonts included in your pubspec.yaml as well as from |
| 18 | +///packages you depend on. |
| 19 | +Future<void> loadAppFonts() async { |
| 20 | + TestWidgetsFlutterBinding.ensureInitialized(); |
| 21 | + final fontManifest = await rootBundle.loadStructuredData<List<dynamic>>( |
| 22 | + 'FontManifest.json', |
| 23 | + (string) async => json.decode(string), |
| 24 | + ); |
24 | 25 |
|
25 | | - final fontsDir = Directory.fromUri(Uri(path: _getPath(from))); |
26 | | - final Map<String, List<ByteData>> fontFamilies = {}; |
27 | | - await for (final entity in fontsDir.list()) { |
28 | | - if (entity.path.endsWith('.ttf')) { |
29 | | - final fontName = |
30 | | - Uri.parse(entity.path).pathSegments.last.split('.ttf').first; |
31 | | - final family = fontName.split('-').first; |
32 | | - final Uint8List bytes = await File.fromUri(entity.uri).readAsBytes(); |
33 | | - final byteData = ByteData.view(bytes.buffer); |
34 | | - fontFamilies[family] = |
35 | | - [byteData].followedBy(fontFamilies[family] ?? []).toList(); |
36 | | - } |
37 | | - } |
38 | | - for (final family in fontFamilies.keys) { |
39 | | - final loader = FontLoader(family); |
40 | | - for (final font in fontFamilies[family]) { |
41 | | - loader.addFont(Future.value(font)); |
| 26 | + for (final Map<String, dynamic> font in fontManifest) { |
| 27 | + final fontLoader = FontLoader(_processedFontFamily(font['family'])); |
| 28 | + for (final Map<String, dynamic> fontType in font['fonts']) { |
| 29 | + fontLoader.addFont(rootBundle.load(fontType['asset'])); |
42 | 30 | } |
43 | | - await loader.load(); |
| 31 | + await fontLoader.load(); |
44 | 32 | } |
45 | | - |
46 | | - _hasLoaded = true; |
47 | 33 | } |
48 | 34 |
|
49 | | -bool _hasLoaded = false; |
50 | | - |
51 | | -String _getPath(String directory) { |
52 | | - if (Directory.current.path.endsWith('test')) { |
53 | | - return '../$directory'; |
54 | | - } else { |
55 | | - return directory; |
| 35 | +String _processedFontFamily(String fontFamily) { |
| 36 | + /// There is no way to easily load the Roboto or Cupertino fonts. |
| 37 | + /// To make them available in tests, a package needs to include their own copies of them. |
| 38 | + /// |
| 39 | + /// GoldenToolkit supplies Roboto because it is free to use. |
| 40 | + /// |
| 41 | + /// However, when a downstream package includes a font, the font family will be prefixed with |
| 42 | + /// /packages/<package name>/<fontFamily> in order to disambiguate when multiple packages include |
| 43 | + /// fonts with the same name. |
| 44 | + /// |
| 45 | + /// Ultimately, the font loader will load whatever we tell it, so if we see a font that looks like |
| 46 | + /// a Material or Cupertino font family, let's treat it as the main font family |
| 47 | + if (fontFamily.startsWith('packages/') && |
| 48 | + _overridableFonts.any(fontFamily.contains)) { |
| 49 | + return fontFamily.split('/').last; |
56 | 50 | } |
| 51 | + return fontFamily; |
57 | 52 | } |
| 53 | + |
| 54 | +const List<String> _overridableFonts = [ |
| 55 | + 'Roboto', |
| 56 | + '.SF UI Display', |
| 57 | + '.SF UI Text', |
| 58 | +]; |
0 commit comments