Commit 49ba9747 authored by Sarah Zakarias's avatar Sarah Zakarias Committed by GitHub

Factor out flutter manifest logic (#12237)

parent a08b5e00
...@@ -5,7 +5,6 @@ ...@@ -5,7 +5,6 @@
import 'dart:async'; import 'dart:async';
import 'dart:convert'; import 'dart:convert';
import 'package:json_schema/json_schema.dart';
import 'package:yaml/yaml.dart'; import 'package:yaml/yaml.dart';
import 'base/file_system.dart'; import 'base/file_system.dart';
...@@ -13,6 +12,7 @@ import 'build_info.dart'; ...@@ -13,6 +12,7 @@ import 'build_info.dart';
import 'cache.dart'; import 'cache.dart';
import 'dart/package_map.dart'; import 'dart/package_map.dart';
import 'devfs.dart'; import 'devfs.dart';
import 'flutter_manifest.dart';
import 'globals.dart'; import 'globals.dart';
/// A bundle of assets. /// A bundle of assets.
...@@ -72,27 +72,16 @@ class AssetBundle { ...@@ -72,27 +72,16 @@ class AssetBundle {
}) async { }) async {
workingDirPath ??= getAssetBuildDirectory(); workingDirPath ??= getAssetBuildDirectory();
packagesPath ??= fs.path.absolute(PackageMap.globalPackagesPath); packagesPath ??= fs.path.absolute(PackageMap.globalPackagesPath);
Object manifest; FlutterManifest flutterManifest;
try { try {
manifest = _loadFlutterManifest(manifestPath); flutterManifest = await FlutterManifest.createFromPath(manifestPath);
if (flutterManifest == null)
return 1;
} catch (e) { } catch (e) {
printStatus('Error detected in pubspec.yaml:', emphasis: true); printStatus('Error detected in pubspec.yaml:', emphasis: true);
printError('$e'); printError('$e');
return 1; return 1;
} }
if (manifest == null) {
// No manifest file found for this application.
entries[_kAssetManifestJson] = new DevFSStringContent('{}');
return 0;
}
if (manifest != null) {
final int result = await _validateFlutterManifest(manifest);
if (result != 0)
return result;
}
Map<String, dynamic> manifestDescriptor = manifest;
final String appName = manifestDescriptor['name'];
manifestDescriptor = manifestDescriptor['flutter'] ?? <String, dynamic>{};
final String assetBasePath = fs.path.dirname(fs.path.absolute(manifestPath)); final String assetBasePath = fs.path.dirname(fs.path.absolute(manifestPath));
_lastBuildTimestamp = new DateTime.now(); _lastBuildTimestamp = new DateTime.now();
...@@ -105,7 +94,7 @@ class AssetBundle { ...@@ -105,7 +94,7 @@ class AssetBundle {
// see _AssetDirectoryCache. // see _AssetDirectoryCache.
final Map<_Asset, List<_Asset>> assetVariants = _parseAssets( final Map<_Asset, List<_Asset>> assetVariants = _parseAssets(
packageMap, packageMap,
manifestDescriptor, flutterManifest,
assetBasePath, assetBasePath,
excludeDirs: <String>[workingDirPath, getBuildDirectory()] excludeDirs: <String>[workingDirPath, getBuildDirectory()]
); );
...@@ -113,47 +102,42 @@ class AssetBundle { ...@@ -113,47 +102,42 @@ class AssetBundle {
if (assetVariants == null) if (assetVariants == null)
return 1; return 1;
final bool usesMaterialDesign = (manifestDescriptor != null) && final List<Map<String, dynamic>> fonts = _parseFonts(
manifestDescriptor.containsKey('uses-material-design') && flutterManifest,
manifestDescriptor['uses-material-design']; includeDefaultFonts,
packageMap,
);
// Add assets from packages. // Add fonts and assets from packages.
final List<Map<String, dynamic>> fonts = <Map<String, dynamic>>[];
for (String packageName in packageMap.map.keys) { for (String packageName in packageMap.map.keys) {
final Uri package = packageMap.map[packageName]; final Uri package = packageMap.map[packageName];
if (package != null && package.scheme == 'file') { if (package != null && package.scheme == 'file') {
final String packageManifestPath = package.resolve('../pubspec.yaml').path; final String packageManifestPath = package.resolve('../pubspec.yaml').path;
final Object packageManifest = _loadFlutterManifest(packageManifestPath); final FlutterManifest packageFlutterManifest = await FlutterManifest.createFromPath(packageManifestPath);
if (packageManifest == null) if (packageFlutterManifest == null)
continue; continue;
final int result = await _validateFlutterManifest(packageManifest); // Skip the app itself
if (result == 0) { if (packageFlutterManifest.appName == flutterManifest.appName)
Map<String, dynamic> packageManifestDescriptor = packageManifest; continue;
// Skip the app itself. final String packageBasePath = fs.path.dirname(packageManifestPath);
if (packageManifestDescriptor['name'] == appName)
continue; final Map<_Asset, List<_Asset>> packageAssets = _parseAssets(
if (packageManifestDescriptor.containsKey('flutter')) { packageMap,
packageManifestDescriptor = packageManifestDescriptor['flutter']; packageFlutterManifest,
final String packageBasePath = fs.path.dirname(packageManifestPath); packageBasePath,
assetVariants.addAll(_parseAssets( packageName: packageName,
packageMap, );
packageManifestDescriptor,
packageBasePath, if (packageAssets == null)
packageName: packageName, return 1;
)); assetVariants.addAll(packageAssets);
final bool packageUsesMaterialDesign = fonts.addAll(_parseFonts(
packageManifestDescriptor.containsKey('uses-material-design') && packageFlutterManifest,
packageManifestDescriptor['uses-material-design']; includeDefaultFonts,
fonts.addAll(_parseFonts( packageMap,
packageManifestDescriptor, packageName: packageName,
packageUsesMaterialDesign, ));
includeDefaultFonts,
packageMap,
packageName: packageName,
));
}
}
} }
} }
...@@ -182,7 +166,7 @@ class AssetBundle { ...@@ -182,7 +166,7 @@ class AssetBundle {
} }
final List<_Asset> materialAssets = <_Asset>[]; final List<_Asset> materialAssets = <_Asset>[];
if (usesMaterialDesign && includeDefaultFonts) { if (flutterManifest.usesMaterialDesign && includeDefaultFonts) {
materialAssets.addAll(_getMaterialAssets(_kFontSetMaterial)); materialAssets.addAll(_getMaterialAssets(_kFontSetMaterial));
} }
for (_Asset asset in materialAssets) { for (_Asset asset in materialAssets) {
...@@ -192,12 +176,6 @@ class AssetBundle { ...@@ -192,12 +176,6 @@ class AssetBundle {
entries[_kAssetManifestJson] = _createAssetManifest(assetVariants); entries[_kAssetManifestJson] = _createAssetManifest(assetVariants);
fonts.addAll(_parseFonts(
manifestDescriptor,
usesMaterialDesign,
includeDefaultFonts,
packageMap,
));
if (fonts.isNotEmpty) if (fonts.isNotEmpty)
entries[_kFontManifestJson] = new DevFSStringContent(JSON.encode(fonts)); entries[_kFontManifestJson] = new DevFSStringContent(JSON.encode(fonts));
...@@ -386,72 +364,61 @@ DevFSContent _createAssetManifest(Map<_Asset, List<_Asset>> assetVariants) { ...@@ -386,72 +364,61 @@ DevFSContent _createAssetManifest(Map<_Asset, List<_Asset>> assetVariants) {
} }
List<Map<String, dynamic>> _parseFonts( List<Map<String, dynamic>> _parseFonts(
Map<String, dynamic> manifestDescriptor, FlutterManifest manifest,
bool usesMaterialDesign,
bool includeDefaultFonts, bool includeDefaultFonts,
PackageMap packageMap, { PackageMap packageMap, {
String packageName String packageName
}) { }) {
final List<Map<String, dynamic>> fonts = <Map<String, dynamic>>[]; final List<Map<String, dynamic>> fonts = <Map<String, dynamic>>[];
if (usesMaterialDesign && includeDefaultFonts) { if (manifest.usesMaterialDesign && includeDefaultFonts) {
fonts.addAll(_getMaterialFonts(AssetBundle._kFontSetMaterial)); fonts.addAll(_getMaterialFonts(AssetBundle._kFontSetMaterial));
} }
if (manifestDescriptor != null && manifestDescriptor.containsKey('fonts')) if (packageName == null) {
if (packageName == null) { fonts.addAll(manifest.fontsDescriptor);
fonts.addAll(manifestDescriptor['fonts']); } else {
} else { fonts.addAll(_createFontsDescriptor(_parsePackageFonts(
fonts.addAll(_parsePackageFonts( manifest,
manifestDescriptor['fonts'], packageName,
packageName, packageMap,
packageMap, )));
)); }
}
return fonts; return fonts;
} }
/// Prefixes family names and asset paths of fonts included from packages with /// Prefixes family names and asset paths of fonts included from packages with
/// 'packages/<package_name> /// 'packages/<package_name>'
/// List<Font> _parsePackageFonts(
/// (e.g., replace {"fonts":[{"asset":"a/bar"}],"family":"bar"} by FlutterManifest manifest,
/// {"fonts":[{"asset":"packages/foo/a/bar"}],"family":"packages/foo/bar"})
List<Map<String, dynamic>> _parsePackageFonts(
List<Map<String, dynamic>> manifestDescriptor,
String packageName, String packageName,
PackageMap packageMap, PackageMap packageMap,
) { ) {
final List<Map<String, dynamic>> parsedFonts = <Map<String, dynamic>>[]; final List<Font> packageFonts = <Font>[];
for (Map<String, dynamic> fontFamily in manifestDescriptor) { for (Font font in manifest.fonts) {
final Map<String, dynamic> parsedFontFamily = <String, dynamic>{}; final List<FontAsset> packageFontAssets = <FontAsset>[];
for (String key in fontFamily.keys) { for (FontAsset fontAsset in font.fontAssets) {
if (key == 'family') { final String assetPath = fontAsset.asset;
parsedFontFamily[key] = 'packages/$packageName/${fontFamily[key]}'; if (assetPath.startsWith('packages') &&
!fs.isFileSync(packageMap.map[packageName].resolve('../$assetPath').path)) {
packageFontAssets.add(new FontAsset(
fontAsset.asset,
weight: fontAsset.weight,
style: fontAsset.style,
));
} else { } else {
assert(key == 'fonts'); packageFontAssets.add(new FontAsset(
final List<Map<String, dynamic>> parsedAssets = <Map<String, dynamic>>[]; 'packages/$packageName/${fontAsset.asset}',
for (Map<String, dynamic> assetProperties in fontFamily[key]) { weight: fontAsset.weight,
final Map<String, dynamic> parsedAssetProperties = <String, dynamic>{}; style: fontAsset.style,
for (String property in assetProperties.keys) { ));
if (property == 'asset') {
final String assetPath = assetProperties[property];
if (assetPath.startsWith('packages') &&
!fs.isFileSync(packageMap.map[packageName].resolve('../$assetPath').path))
parsedAssetProperties[property] = assetProperties[property];
else
parsedAssetProperties[property] = 'packages/$packageName/${assetProperties[property]}';
} else {
assert(property == 'style' || property == 'weight');
parsedAssetProperties[property] = assetProperties[property];
}
}
parsedAssets.add(parsedAssetProperties);
}
parsedFontFamily[key] = parsedAssets;
} }
} }
parsedFonts.add(parsedFontFamily); packageFonts.add(new Font('packages/$packageName/${font.familyName}', packageFontAssets));
} }
return packageFonts;
}
return parsedFonts; List<Map<String, dynamic>> _createFontsDescriptor(List<Font> fonts) {
return fonts.map((Font font) => font.descriptor).toList();
} }
// Given an assets directory like this: // Given an assets directory like this:
...@@ -504,63 +471,48 @@ class _AssetDirectoryCache { ...@@ -504,63 +471,48 @@ class _AssetDirectoryCache {
/// Returns null on missing assets. /// Returns null on missing assets.
Map<_Asset, List<_Asset>> _parseAssets( Map<_Asset, List<_Asset>> _parseAssets(
PackageMap packageMap, PackageMap packageMap,
Map<String, dynamic> manifestDescriptor, FlutterManifest flutterManifest,
String assetBase, { String assetBase, {
List<String> excludeDirs: const <String>[], List<String> excludeDirs: const <String>[],
String packageName String packageName
}) { }) {
final Map<_Asset, List<_Asset>> result = <_Asset, List<_Asset>>{}; final Map<_Asset, List<_Asset>> result = <_Asset, List<_Asset>>{};
if (manifestDescriptor == null) final _AssetDirectoryCache cache = new _AssetDirectoryCache(excludeDirs);
return result; for (String assetName in flutterManifest.assets) {
final _Asset asset = _resolveAsset(
packageMap,
assetBase,
assetName,
packageName,
);
final List<_Asset> variants = <_Asset>[];
for (String path in cache.variantsFor(asset.assetFile.path)) {
final String key = fs.path.relative(path, from: asset.base);
String assetEntry;
if (asset.symbolicPrefix != null)
assetEntry = fs.path.join(asset.symbolicPrefix, key);
variants.add(new _Asset(base: asset.base, assetEntry: assetEntry, relativePath: key));
}
if (manifestDescriptor.containsKey('assets')) { result[asset] = variants;
final _AssetDirectoryCache cache = new _AssetDirectoryCache(excludeDirs); }
for (String assetName in manifestDescriptor['assets']) {
final _Asset asset = _resolveAsset( // Add assets referenced in the fonts section of the manifest.
for (Font font in flutterManifest.fonts) {
for (FontAsset fontAsset in font.fontAssets) {
final _Asset baseAsset = _resolveAsset(
packageMap, packageMap,
assetBase, assetBase,
assetName, fontAsset.asset,
packageName, packageName,
); );
final List<_Asset> variants = <_Asset>[]; if (!baseAsset.assetFileExists) {
for (String path in cache.variantsFor(asset.assetFile.path)) { printError('Error: unable to locate asset entry in pubspec.yaml: "${fontAsset.asset}".');
final String key = fs.path.relative(path, from: asset.base); return null;
String assetEntry;
if (asset.symbolicPrefix != null)
assetEntry = fs.path.join(asset.symbolicPrefix, key);
variants.add(new _Asset(base: asset.base, assetEntry: assetEntry, relativePath: key));
} }
result[asset] = variants; result[baseAsset] = <_Asset>[];
}
}
// Add assets referenced in the fonts section of the manifest.
if (manifestDescriptor.containsKey('fonts')) {
for (Map<String, dynamic> family in manifestDescriptor['fonts']) {
final List<Map<String, dynamic>> fonts = family['fonts'];
if (fonts == null)
continue;
for (Map<String, dynamic> font in fonts) {
final String asset = font['asset'];
if (asset == null)
continue;
final _Asset baseAsset = _resolveAsset(
packageMap,
assetBase,
asset,
packageName,
);
if (!baseAsset.assetFileExists) {
printError('Error: unable to locate asset entry in pubspec.yaml: "$asset".');
return null;
}
result[baseAsset] = <_Asset>[];
}
} }
} }
...@@ -613,25 +565,3 @@ _Asset _resolvePackageAsset(String asset, PackageMap packageMap) { ...@@ -613,25 +565,3 @@ _Asset _resolvePackageAsset(String asset, PackageMap packageMap) {
printError('Could not resolve package $packageKey for asset $asset.\n'); printError('Could not resolve package $packageKey for asset $asset.\n');
return null; return null;
} }
dynamic _loadFlutterManifest(String manifestPath) {
if (manifestPath == null || !fs.isFileSync(manifestPath))
return null;
final String manifestDescriptor = fs.file(manifestPath).readAsStringSync();
return loadYaml(manifestDescriptor);
}
Future<int> _validateFlutterManifest(Object manifest) async {
final String schemaPath = fs.path.join(fs.path.absolute(Cache.flutterRoot),
'packages', 'flutter_tools', 'schema', 'pubspec_yaml.json');
final Schema schema = await Schema.createSchemaFromUrl(fs.path.toUri(schemaPath).toString());
final Validator validator = new Validator(schema);
if (validator.validate(manifest)) {
return 0;
} else {
printStatus('Error detected in pubspec.yaml:', emphasis: true);
printError(validator.errors.join('\n'));
return 1;
}
}
// Copyright 2017 The Chromium 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 'package:flutter_tools/src/globals.dart';
import 'package:json_schema/json_schema.dart';
import 'package:yaml/yaml.dart';
import 'base/file_system.dart';
import 'cache.dart';
/// A wrapper around the `flutter` section in the `pubspec.yaml` file.
class FlutterManifest {
FlutterManifest._();
/// Returns null on missing or invalid manifest
static Future<FlutterManifest> createFromPath(String path) async {
return _createFromYaml(await _loadFlutterManifest(path));
}
/// Returns null on missing or invalid manifest
static Future<FlutterManifest> createFromString(String manifest) async {
return _createFromYaml(loadYaml(manifest));
}
static Future<FlutterManifest> _createFromYaml(Object yamlDocument) async {
final FlutterManifest pubspec = new FlutterManifest._();
if (yamlDocument == null || !await _validate(yamlDocument))
return null;
pubspec._descriptor = yamlDocument;
pubspec._flutterDescriptor = pubspec._descriptor['flutter'] ?? <String, dynamic>{};
return pubspec;
}
/// A map representation of the entire `pubspec.yaml` file.
Map<String, dynamic> _descriptor;
/// A map representation of the `flutter` section in the `pubspec.yaml` file.
Map<String, dynamic> _flutterDescriptor;
String get appName => _descriptor['name'];
bool get usesMaterialDesign {
return _flutterDescriptor['uses-material-design'] ?? false;
}
List<Map<String, dynamic>> get fontsDescriptor {
return _flutterDescriptor['fonts'] ?? const <Map<String, dynamic>>[];
}
List<String> get assets {
return _flutterDescriptor['assets'] ?? const <String>[];
}
List<Font> _fonts;
List<Font> get fonts {
_fonts ??= _extractFonts();
return _fonts;
}
List<Font> _extractFonts() {
if (!_flutterDescriptor.containsKey('fonts'))
return <Font>[];
final List<Font> fonts = <Font>[];
for (Map<String, dynamic> fontFamily in _flutterDescriptor['fonts']) {
final List<Map<String, dynamic>> fontFiles = fontFamily['fonts'];
final String familyName = fontFamily['family'];
if (familyName == null) {
printError('Warning: Missing family name for font.', emphasis: true);
continue;
}
if (fontFiles == null) {
printError('Warning: No fonts specified for font $familyName', emphasis: true);
continue;
}
final List<FontAsset> fontAssets = <FontAsset>[];
for (Map<String, dynamic> fontFile in fontFiles) {
final String asset = fontFile['asset'];
if (asset == null) {
printError('Warning: Missing asset in fonts for $familyName', emphasis: true);
continue;
}
fontAssets.add(new FontAsset(
asset,
weight: fontFile['weight'],
style: fontFile['style'],
));
}
if (fontAssets.isNotEmpty)
fonts.add(new Font(fontFamily['family'], fontAssets));
}
return fonts;
}
}
class Font {
Font(this.familyName, this.fontAssets) {
assert(familyName != null);
assert(fontAssets != null);
assert(fontAssets.isNotEmpty);
}
final String familyName;
final List<FontAsset> fontAssets;
Map<String, dynamic> get descriptor {
return <String, dynamic>{
'family': familyName,
'fonts': fontAssets.map((FontAsset a) => a.descriptor).toList(),
};
}
@override
String toString() => '$runtimeType(family: $familyName, assets: $fontAssets)';
}
class FontAsset {
FontAsset(this.asset, {this.weight, this.style}) {
assert(asset != null);
}
final String asset;
final int weight;
final String style;
Map<String, dynamic> get descriptor {
final Map<String, dynamic> descriptor = <String, dynamic>{};
if (weight != null)
descriptor['weight'] = weight;
if (style != null)
descriptor['style'] = style;
descriptor['asset'] = asset;
return descriptor;
}
@override
String toString() => '$runtimeType(asset: $asset, weight; $weight, style: $style)';
}
Future<dynamic> _loadFlutterManifest(String manifestPath) async {
if (manifestPath == null || !fs.isFileSync(manifestPath))
return null;
final String manifestDescriptor = await fs.file(manifestPath).readAsString();
return loadYaml(manifestDescriptor);
}
Future<bool> _validate(Object manifest) async {
final String schemaPath = fs.path.join(
fs.path.absolute(Cache.flutterRoot), 'packages', 'flutter_tools', 'schema',
'pubspec_yaml.json',
);
final Schema schema = await Schema.createSchemaFromUrl(fs.path.toUri(schemaPath).toString());
final Validator validator = new Validator(schema);
if (validator.validate(manifest)) {
return true;
} else {
printStatus('Error detected in pubspec.yaml:', emphasis: true);
printError(validator.errors.join('\n'));
return false;
}
}
\ No newline at end of file
...@@ -180,8 +180,8 @@ $fontsSection ...@@ -180,8 +180,8 @@ $fontsSection
writeFontAsset('p/p/', font); writeFontAsset('p/p/', font);
final String expectedFontManifest = final String expectedFontManifest =
'[{"fonts":[{"asset":"packages/test_package/a/bar"}],' '[{"family":"packages/test_package/foo",'
'"family":"packages/test_package/foo"}]'; '"fonts":[{"asset":"packages/test_package/a/bar"}]}]';
await buildAndVerifyFonts( await buildAndVerifyFonts(
<String>[], <String>[],
<String>[font], <String>[font],
...@@ -211,8 +211,8 @@ $fontsSection ...@@ -211,8 +211,8 @@ $fontsSection
writeFontAsset('p2/p/lib/', font); writeFontAsset('p2/p/lib/', font);
final String expectedFontManifest = final String expectedFontManifest =
'[{"fonts":[{"asset":"packages/test_package2/bar"}],' '[{"family":"packages/test_package/foo",'
'"family":"packages/test_package/foo"}]'; '"fonts":[{"asset":"packages/test_package2/bar"}]}]';
await buildAndVerifyFonts( await buildAndVerifyFonts(
<String>[], <String>[],
<String>[font], <String>[font],
...@@ -243,8 +243,8 @@ $fontsSection ...@@ -243,8 +243,8 @@ $fontsSection
writeFontAsset('p/p/', font); writeFontAsset('p/p/', font);
final String expectedFontManifest = final String expectedFontManifest =
'[{"fonts":[{"weight":400,"style":"italic","asset":"packages/test_package/a/bar"}],' '[{"family":"packages/test_package/foo",'
'"family":"packages/test_package/foo"}]'; '"fonts":[{"weight":400,"style":"italic","asset":"packages/test_package/a/bar"}]}]';
await buildAndVerifyFonts( await buildAndVerifyFonts(
<String>[], <String>[],
<String>[font], <String>[font],
...@@ -278,9 +278,9 @@ $fontsSection ...@@ -278,9 +278,9 @@ $fontsSection
writeFontAsset('p/p/', font); writeFontAsset('p/p/', font);
final String expectedFontManifest = final String expectedFontManifest =
'[{"fonts":[{"asset":"packages/test_package/a/bar"}],' '[{"fonts":[{"asset":"a/bar"}],"family":"foo"},'
'"family":"packages/test_package/foo"},' '{"family":"packages/test_package/foo",'
'{"fonts":[{"asset":"a/bar"}],"family":"foo"}]'; '"fonts":[{"asset":"packages/test_package/a/bar"}]}]';
await buildAndVerifyFonts( await buildAndVerifyFonts(
<String>[font], <String>[font],
<String>[font], <String>[font],
......
// Copyright 2017 The Chromium 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 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/flutter_manifest.dart';
import 'package:test/test.dart';
import 'src/common.dart';
import 'src/context.dart';
void main() {
setUpAll(() {
Cache.flutterRoot = getFlutterRoot();
});
group('FlutterManifest', () {
test('has no fonts or assets when the "flutter" section is empty', () async {
final String manifest = '''
name: test
dependencies:
flutter:
sdk: flutter
''';
final FlutterManifest flutterManifest = await FlutterManifest.createFromString(manifest);
expect(flutterManifest, isNotNull);
expect(flutterManifest.appName, 'test');
expect(flutterManifest.usesMaterialDesign, false);
expect(flutterManifest.fontsDescriptor, isEmpty);
expect(flutterManifest.fonts, isEmpty);
expect(flutterManifest.assets, isEmpty);
});
test('knows if material design is used', () async {
final String manifest = '''
name: test
dependencies:
flutter:
sdk: flutter
flutter:
uses-material-design: true
''';
final FlutterManifest flutterManifest = await FlutterManifest.createFromString(manifest);
expect(flutterManifest.usesMaterialDesign, true);
});
test('has two assets', () async {
final String manifest = '''
name: test
dependencies:
flutter:
sdk: flutter
flutter:
uses-material-design: true
assets:
- a/foo
- a/bar
''';
final FlutterManifest flutterManifest = await FlutterManifest.createFromString(manifest);
expect(flutterManifest.assets, <String>['a/foo', 'a/bar']);
});
test('has one font family with one asset', () async {
final String manifest = '''
name: test
dependencies:
flutter:
sdk: flutter
flutter:
uses-material-design: true
fonts:
- family: foo
fonts:
- asset: a/bar
''';
final FlutterManifest flutterManifest = await FlutterManifest.createFromString(manifest);
expect(flutterManifest.fontsDescriptor.toString(), '[{fonts: [{asset: a/bar}], family: foo}]');
final List<Font> fonts = flutterManifest.fonts;
expect(fonts.length, 1);
final Font font = fonts[0];
final String fontDescriptor = '{family: foo, fonts: [{asset: a/bar}]}';
expect(font.descriptor.toString(), fontDescriptor);
expect(font.familyName, 'foo');
final List<FontAsset> assets = font.fontAssets;
expect(assets.length, 1);
final FontAsset fontAsset = assets[0];
expect(fontAsset.asset, 'a/bar');
expect(fontAsset.weight, isNull);
expect(fontAsset.style, isNull);
});
test('has one font family with a simple asset and one with weight', () async {
final String manifest = '''
name: test
dependencies:
flutter:
sdk: flutter
flutter:
uses-material-design: true
fonts:
- family: foo
fonts:
- asset: a/bar
- asset: a/bar
weight: 400
''';
final FlutterManifest flutterManifest = await FlutterManifest.createFromString(manifest);
final String expectedFontsDescriptor = '[{fonts: [{asset: a/bar}, {weight: 400, asset: a/bar}], family: foo}]';
expect(flutterManifest.fontsDescriptor.toString(), expectedFontsDescriptor);
final List<Font> fonts = flutterManifest.fonts;
expect(fonts.length, 1);
final Font font = fonts[0];
final String fontDescriptor = '{family: foo, fonts: [{asset: a/bar}, {weight: 400, asset: a/bar}]}';
expect(font.descriptor.toString(), fontDescriptor);
expect(font.familyName, 'foo');
final List<FontAsset> assets = font.fontAssets;
expect(assets.length, 2);
final FontAsset fontAsset0 = assets[0];
expect(fontAsset0.asset, 'a/bar');
expect(fontAsset0.weight, isNull);
expect(fontAsset0.style, isNull);
final FontAsset fontAsset1 = assets[1];
expect(fontAsset1.asset, 'a/bar');
expect(fontAsset1.weight, 400);
expect(fontAsset1.style, isNull);
});
test('has one font family with a simple asset and one with weight and style', () async {
final String manifest = '''
name: test
dependencies:
flutter:
sdk: flutter
flutter:
uses-material-design: true
fonts:
- family: foo
fonts:
- asset: a/bar
- asset: a/bar
weight: 400
style: italic
''';
final FlutterManifest flutterManifest = await FlutterManifest.createFromString(manifest);
final String expectedFontsDescriptor = '[{fonts: [{asset: a/bar}, {style: italic, weight: 400, asset: a/bar}], family: foo}]';
expect(flutterManifest.fontsDescriptor.toString(), expectedFontsDescriptor);
final List<Font> fonts = flutterManifest.fonts;
expect(fonts.length, 1);
final Font font = fonts[0];
final String fontDescriptor = '{family: foo, fonts: [{asset: a/bar}, {weight: 400, style: italic, asset: a/bar}]}';
expect(font.descriptor.toString(), fontDescriptor);
expect(font.familyName, 'foo');
final List<FontAsset> assets = font.fontAssets;
expect(assets.length, 2);
final FontAsset fontAsset0 = assets[0];
expect(fontAsset0.asset, 'a/bar');
expect(fontAsset0.weight, isNull);
expect(fontAsset0.style, isNull);
final FontAsset fontAsset1 = assets[1];
expect(fontAsset1.asset, 'a/bar');
expect(fontAsset1.weight, 400);
expect(fontAsset1.style, 'italic');
});
test('has two font families, each with one simple asset and one with weight and style', () async {
final String manifest = '''
name: test
dependencies:
flutter:
sdk: flutter
flutter:
uses-material-design: true
fonts:
- family: foo
fonts:
- asset: a/bar
- asset: a/bar
weight: 400
style: italic
- family: bar
fonts:
- asset: a/baz
- weight: 400
asset: a/baz
style: italic
''';
final FlutterManifest flutterManifest = await FlutterManifest.createFromString(manifest);
final String expectedFontsDescriptor = '[{fonts: [{asset: a/bar}, {style: italic, weight: 400, asset: a/bar}], family: foo},'
' {fonts: [{asset: a/baz}, {style: italic, weight: 400, asset: a/baz}], family: bar}]';
expect(flutterManifest.fontsDescriptor.toString(), expectedFontsDescriptor);
final List<Font> fonts = flutterManifest.fonts;
expect(fonts.length, 2);
final Font fooFont = fonts[0];
final String barFontDescriptor = '{family: foo, fonts: [{asset: a/bar}, {weight: 400, style: italic, asset: a/bar}]}';
expect(fooFont.descriptor.toString(), barFontDescriptor);
expect(fooFont.familyName, 'foo');
final List<FontAsset> fooAassets = fooFont.fontAssets;
expect(fooAassets.length, 2);
final FontAsset fooFontAsset0 = fooAassets[0];
expect(fooFontAsset0.asset, 'a/bar');
expect(fooFontAsset0.weight, isNull);
expect(fooFontAsset0.style, isNull);
final FontAsset fooFontAsset1 = fooAassets[1];
expect(fooFontAsset1.asset, 'a/bar');
expect(fooFontAsset1.weight, 400);
expect(fooFontAsset1.style, 'italic');
final Font barFont = fonts[1];
final String fontDescriptor = '{family: bar, fonts: [{asset: a/baz}, {weight: 400, style: italic, asset: a/baz}]}';
expect(barFont.descriptor.toString(), fontDescriptor);
expect(barFont.familyName, 'bar');
final List<FontAsset> barAssets = barFont.fontAssets;
expect(barAssets.length, 2);
final FontAsset barFontAsset0 = barAssets[0];
expect(barFontAsset0.asset, 'a/baz');
expect(barFontAsset0.weight, isNull);
expect(barFontAsset0.style, isNull);
final FontAsset barFontAsset1 = barAssets[1];
expect(barFontAsset1.asset, 'a/baz');
expect(barFontAsset1.weight, 400);
expect(barFontAsset1.style, 'italic');
});
testUsingContext('has only one of two font familes when one declaration is missing the "family" option', () async {
final String manifest = '''
name: test
dependencies:
flutter:
sdk: flutter
flutter:
uses-material-design: true
fonts:
- family: foo
fonts:
- asset: a/bar
- asset: a/bar
weight: 400
style: italic
- fonts:
- asset: a/baz
- asset: a/baz
weight: 400
style: italic
''';
final FlutterManifest flutterManifest = await FlutterManifest.createFromString(manifest);
final String expectedFontsDescriptor = '[{fonts: [{asset: a/bar}, {style: italic, weight: 400, asset: a/bar}], family: foo},'
' {fonts: [{asset: a/baz}, {style: italic, weight: 400, asset: a/baz}]}]';
expect(flutterManifest.fontsDescriptor.toString(), expectedFontsDescriptor);
final List<Font> fonts = flutterManifest.fonts;
expect(fonts.length, 1);
final Font fooFont = fonts[0];
final String barFontDescriptor = '{family: foo, fonts: [{asset: a/bar}, {weight: 400, style: italic, asset: a/bar}]}';
expect(fooFont.descriptor.toString(), barFontDescriptor);
expect(fooFont.familyName, 'foo');
final List<FontAsset> fooAassets = fooFont.fontAssets;
expect(fooAassets.length, 2);
final FontAsset fooFontAsset0 = fooAassets[0];
expect(fooFontAsset0.asset, 'a/bar');
expect(fooFontAsset0.weight, isNull);
expect(fooFontAsset0.style, isNull);
final FontAsset fooFontAsset1 = fooAassets[1];
expect(fooFontAsset1.asset, 'a/bar');
expect(fooFontAsset1.weight, 400);
expect(fooFontAsset1.style, 'italic');
});
testUsingContext('has only one of two font familes when one declaration is missing the "fonts" option', () async {
final String manifest = '''
name: test
dependencies:
flutter:
sdk: flutter
flutter:
uses-material-design: true
fonts:
- family: foo
fonts:
- asset: a/bar
- asset: a/bar
weight: 400
style: italic
- family: bar
''';
final FlutterManifest flutterManifest = await FlutterManifest.createFromString(manifest);
final String expectedFontsDescriptor = '[{fonts: [{asset: a/bar}, {style: italic, weight: 400, asset: a/bar}], family: foo},'
' {family: bar}]';
expect(flutterManifest.fontsDescriptor.toString(), expectedFontsDescriptor);
final List<Font> fonts = flutterManifest.fonts;
expect(fonts.length, 1);
final Font fooFont = fonts[0];
final String barFontDescriptor = '{family: foo, fonts: [{asset: a/bar}, {weight: 400, style: italic, asset: a/bar}]}';
expect(fooFont.descriptor.toString(), barFontDescriptor);
expect(fooFont.familyName, 'foo');
final List<FontAsset> fooAassets = fooFont.fontAssets;
expect(fooAassets.length, 2);
final FontAsset fooFontAsset0 = fooAassets[0];
expect(fooFontAsset0.asset, 'a/bar');
expect(fooFontAsset0.weight, isNull);
expect(fooFontAsset0.style, isNull);
final FontAsset fooFontAsset1 = fooAassets[1];
expect(fooFontAsset1.asset, 'a/bar');
expect(fooFontAsset1.weight, 400);
expect(fooFontAsset1.style, 'italic');
});
testUsingContext('has no font family when declaration is missing the "asset" option', () async {
final String manifest = '''
name: test
dependencies:
flutter:
sdk: flutter
flutter:
uses-material-design: true
fonts:
- family: foo
fonts:
- weight: 400
''';
final FlutterManifest flutterManifest = await FlutterManifest.createFromString(manifest);
final String expectedFontsDescriptor = '[{fonts: [{weight: 400}], family: foo}]';
expect(flutterManifest.fontsDescriptor.toString(), expectedFontsDescriptor);
final List<Font> fonts = flutterManifest.fonts;
expect(fonts.length, 0);
});
});
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment