| // Copyright 2013 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:convert'; |
| import 'dart:typed_data'; |
| |
| import 'package:test/bootstrap/browser.dart'; |
| import 'package:test/test.dart'; |
| import 'package:ui/src/engine.dart'; |
| |
| import '../common/fake_asset_manager.dart'; |
| import '../common/test_initialization.dart'; |
| import 'utils.dart'; |
| |
| void main() { |
| internalBootstrapBrowserTest(() => testMain); |
| } |
| |
| Future<void> testMain() async { |
| setUpUnitTests(); |
| |
| late FakeAssetScope testScope; |
| setUp(() { |
| mockHttpFetchResponseFactory = null; |
| testScope = fakeAssetManager.pushAssetScope(); |
| }); |
| |
| tearDown(() { |
| fakeAssetManager.popAssetScope(testScope); |
| }); |
| |
| test('Loading valid font from data succeeds without family name (except in HTML renderer)', () async { |
| final FlutterFontCollection collection = renderer.fontCollection; |
| final ByteBuffer ahemData = await httpFetchByteBuffer('/assets/fonts/ahem.ttf'); |
| expect( |
| await collection.loadFontFromList(ahemData.asUint8List()), |
| !isHtml, // HtmlFontCollection requires family name |
| ); |
| }); |
| |
| test('Loading valid font from data succeeds with family name', () async { |
| final FlutterFontCollection collection = renderer.fontCollection; |
| final ByteBuffer ahemData = await httpFetchByteBuffer('/assets/fonts/ahem.ttf'); |
| expect( |
| await collection.loadFontFromList(ahemData.asUint8List(), fontFamily: 'FamilyName'), |
| true |
| ); |
| }); |
| |
| test('Loading invalid font from data returns false', () async { |
| final FlutterFontCollection collection = renderer.fontCollection; |
| final List<int> invalidFontData = utf8.encode('This is not valid font data'); |
| expect( |
| await collection.loadFontFromList(Uint8List.fromList(invalidFontData), fontFamily: 'FamilyName'), |
| false |
| ); |
| }); |
| |
| test('Loading valid asset fonts succeds', () async { |
| testScope.setAssetPassthrough(robotoVariableFontUrl); |
| testScope.setAssetPassthrough(robotoTestFontUrl); |
| testScope.setAssetPassthrough(ahemFontUrl); |
| |
| final FlutterFontCollection collection = renderer.fontCollection; |
| final AssetFontsResult result = await collection.loadAssetFonts(FontManifest(<FontFamily>[ |
| FontFamily(robotoFontFamily, <FontAsset>[ |
| FontAsset(robotoVariableFontUrl, <String, String>{}), |
| FontAsset(robotoTestFontUrl, <String, String>{'weight': 'bold'}), |
| ]), |
| FontFamily(ahemFontFamily, <FontAsset>[ |
| FontAsset(ahemFontUrl, <String, String>{}) |
| ]), |
| ])); |
| expect(result.loadedFonts, <String>[ |
| robotoVariableFontUrl, |
| robotoTestFontUrl, |
| ahemFontUrl, |
| ]); |
| expect(result.fontFailures, isEmpty); |
| }); |
| |
| test('Loading asset fonts reports when font not found', () async { |
| testScope.setAssetPassthrough(robotoVariableFontUrl); |
| testScope.setAssetPassthrough(robotoTestFontUrl); |
| |
| const String invalidFontUrl = 'assets/invalid_font_url.ttf'; |
| |
| final FlutterFontCollection collection = renderer.fontCollection; |
| final AssetFontsResult result = await collection.loadAssetFonts(FontManifest(<FontFamily>[ |
| FontFamily(robotoFontFamily, <FontAsset>[ |
| FontAsset(robotoVariableFontUrl, <String, String>{}), |
| FontAsset(robotoTestFontUrl, <String, String>{'weight': 'bold'}), |
| ]), |
| FontFamily(ahemFontFamily, <FontAsset>[ |
| FontAsset(invalidFontUrl, <String, String>{}) |
| ]), |
| ])); |
| expect(result.loadedFonts, <String>[ |
| robotoVariableFontUrl, |
| robotoTestFontUrl, |
| ]); |
| expect(result.fontFailures, hasLength(1)); |
| if (isHtml) { |
| // The HTML renderer doesn't have a way to differentiate 404's from other |
| // download errors. |
| expect(result.fontFailures[invalidFontUrl], isA<FontDownloadError>()); |
| } else { |
| expect(result.fontFailures[invalidFontUrl], isA<FontNotFoundError>()); |
| } |
| }); |
| |
| test('Loading asset fonts reports when a font has invalid data', () async { |
| const String invalidFontUrl = 'assets/invalid_font_data.ttf'; |
| |
| testScope.setAssetPassthrough(robotoVariableFontUrl); |
| testScope.setAssetPassthrough(robotoTestFontUrl); |
| testScope.setAssetPassthrough(invalidFontUrl); |
| |
| mockHttpFetchResponseFactory = (String url) async { |
| if (url == invalidFontUrl) { |
| return MockHttpFetchResponse( |
| url: url, |
| status: 200, |
| payload: MockHttpFetchPayload( |
| byteBuffer: stringAsUtf8Data('this is invalid data').buffer |
| ), |
| ); |
| } |
| return null; |
| }; |
| |
| final FlutterFontCollection collection = renderer.fontCollection; |
| final AssetFontsResult result = await collection.loadAssetFonts(FontManifest(<FontFamily>[ |
| FontFamily(robotoFontFamily, <FontAsset>[ |
| FontAsset(robotoVariableFontUrl, <String, String>{}), |
| FontAsset(robotoTestFontUrl, <String, String>{'weight': 'bold'}), |
| ]), |
| FontFamily(ahemFontFamily, <FontAsset>[ |
| FontAsset(invalidFontUrl, <String, String>{}) |
| ]), |
| ])); |
| expect(result.loadedFonts, <String>[ |
| robotoVariableFontUrl, |
| robotoTestFontUrl, |
| ]); |
| expect(result.fontFailures, hasLength(1)); |
| if (isHtml) { |
| // The HTML renderer doesn't have a way to differentiate invalid data |
| // from other download errors. |
| expect(result.fontFailures[invalidFontUrl], isA<FontDownloadError>()); |
| } else { |
| expect(result.fontFailures[invalidFontUrl], isA<FontInvalidDataError>()); |
| } |
| }); |
| |
| test('Font manifest with numeric and string descriptor values parses correctly', () async { |
| testScope.setAsset('FontManifest.json', stringAsUtf8Data(r''' |
| [ |
| { |
| "family": "FakeFont", |
| "fonts": [ |
| { |
| "asset": "fonts/FakeFont.ttf", |
| "style": "italic", |
| "weight": 400 |
| } |
| ] |
| } |
| ] |
| ''')); |
| final FontManifest manifest = await fetchFontManifest(fakeAssetManager); |
| expect(manifest.families.length, 1); |
| |
| final FontFamily family = manifest.families.single; |
| expect(family.name, 'FakeFont'); |
| expect(family.fontAssets.length, 1); |
| |
| final FontAsset fontAsset = family.fontAssets.single; |
| expect(fontAsset.asset, 'fonts/FakeFont.ttf'); |
| expect(fontAsset.descriptors.length, 2); |
| expect(fontAsset.descriptors['style'], 'italic'); |
| expect(fontAsset.descriptors['weight'], '400'); |
| }); |
| } |