[flutter_tools] refactor FlutterManifest to be context-free (#54555)
diff --git a/packages/flutter_tools/lib/src/asset.dart b/packages/flutter_tools/lib/src/asset.dart
index c2c33d1..6db13de 100644
--- a/packages/flutter_tools/lib/src/asset.dart
+++ b/packages/flutter_tools/lib/src/asset.dart
@@ -128,7 +128,11 @@
packagesPath ??= globals.fs.path.absolute(PackageMap.globalPackagesPath);
FlutterManifest flutterManifest;
try {
- flutterManifest = FlutterManifest.createFromPath(manifestPath);
+ flutterManifest = FlutterManifest.createFromPath(
+ manifestPath,
+ logger: globals.logger,
+ fileSystem: globals.fs,
+ );
} on Exception catch (e) {
globals.printStatus('Error detected in pubspec.yaml:', emphasis: true);
globals.printError('$e');
@@ -187,7 +191,11 @@
final Uri packageUri = package.packageUriRoot;
if (packageUri != null && packageUri.scheme == 'file') {
final String packageManifestPath = globals.fs.path.fromUri(packageUri.resolve('../pubspec.yaml'));
- final FlutterManifest packageFlutterManifest = FlutterManifest.createFromPath(packageManifestPath);
+ final FlutterManifest packageFlutterManifest = FlutterManifest.createFromPath(
+ packageManifestPath,
+ logger: globals.logger,
+ fileSystem: globals.fs,
+ );
if (packageFlutterManifest == null) {
continue;
}
diff --git a/packages/flutter_tools/lib/src/flutter_manifest.dart b/packages/flutter_tools/lib/src/flutter_manifest.dart
index b86ca76..aa3e9b4 100644
--- a/packages/flutter_tools/lib/src/flutter_manifest.dart
+++ b/packages/flutter_tools/lib/src/flutter_manifest.dart
@@ -7,42 +7,45 @@
import 'package:yaml/yaml.dart';
import 'base/file_system.dart';
+import 'base/logger.dart';
import 'base/user_messages.dart';
import 'base/utils.dart';
import 'cache.dart';
-import 'globals.dart' as globals;
import 'plugins.dart';
/// A wrapper around the `flutter` section in the `pubspec.yaml` file.
class FlutterManifest {
- FlutterManifest._();
+ FlutterManifest._(this._logger);
/// Returns an empty manifest.
- static FlutterManifest empty() {
- final FlutterManifest manifest = FlutterManifest._();
+ factory FlutterManifest.empty({ @required Logger logger }) {
+ final FlutterManifest manifest = FlutterManifest._(logger);
manifest._descriptor = const <String, dynamic>{};
manifest._flutterDescriptor = const <String, dynamic>{};
return manifest;
}
/// Returns null on invalid manifest. Returns empty manifest on missing file.
- static FlutterManifest createFromPath(String path) {
- if (path == null || !globals.fs.isFileSync(path)) {
- return _createFromYaml(null);
+ static FlutterManifest createFromPath(String path, {
+ @required FileSystem fileSystem,
+ @required Logger logger,
+ }) {
+ if (path == null || !fileSystem.isFileSync(path)) {
+ return _createFromYaml(null, logger);
}
- final String manifest = globals.fs.file(path).readAsStringSync();
- return createFromString(manifest);
+ final String manifest = fileSystem.file(path).readAsStringSync();
+ return FlutterManifest.createFromString(manifest, logger: logger);
}
/// Returns null on missing or invalid manifest
@visibleForTesting
- static FlutterManifest createFromString(String manifest) {
- return _createFromYaml(loadYaml(manifest) as YamlMap);
+ static FlutterManifest createFromString(String manifest, { @required Logger logger }) {
+ return _createFromYaml(loadYaml(manifest) as YamlMap, logger);
}
- static FlutterManifest _createFromYaml(YamlMap yamlDocument) {
- final FlutterManifest pubspec = FlutterManifest._();
- if (yamlDocument != null && !_validate(yamlDocument)) {
+ static FlutterManifest _createFromYaml(YamlMap yamlDocument, Logger logger) {
+ final FlutterManifest pubspec = FlutterManifest._(logger);
+ if (yamlDocument != null && !_validate(yamlDocument, logger)) {
return null;
}
@@ -63,6 +66,8 @@
return pubspec;
}
+ final Logger _logger;
+
/// A map representation of the entire `pubspec.yaml` file.
Map<String, dynamic> _descriptor;
@@ -91,7 +96,7 @@
version = Version.parse(verStr);
} on Exception {
if (!_hasShowInvalidVersionMsg) {
- globals.printStatus(userMessages.invalidVersionSettingHintMessage(verStr), emphasis: true);
+ _logger.printStatus(userMessages.invalidVersionSettingHintMessage(verStr), emphasis: true);
_hasShowInvalidVersionMsg = true;
}
}
@@ -203,14 +208,14 @@
final List<Uri> results = <Uri>[];
for (final Object asset in assets) {
if (asset is! String || asset == null || asset == '') {
- globals.printError('Asset manifest contains a null or empty uri.');
+ _logger.printError('Asset manifest contains a null or empty uri.');
continue;
}
final String stringAsset = asset as String;
try {
results.add(Uri(pathSegments: stringAsset.split('/')));
} on FormatException {
- globals.printError('Asset manifest contains invalid uri: $asset.');
+ _logger.printError('Asset manifest contains invalid uri: $asset.');
}
}
return results;
@@ -233,11 +238,11 @@
final YamlList fontFiles = fontFamily['fonts'] as YamlList;
final String familyName = fontFamily['family'] as String;
if (familyName == null) {
- globals.printError('Warning: Missing family name for font.', emphasis: true);
+ _logger.printError('Warning: Missing family name for font.', emphasis: true);
continue;
}
if (fontFiles == null) {
- globals.printError('Warning: No fonts specified for font $familyName', emphasis: true);
+ _logger.printError('Warning: No fonts specified for font $familyName', emphasis: true);
continue;
}
@@ -245,7 +250,7 @@
for (final Map<dynamic, dynamic> fontFile in fontFiles.cast<Map<dynamic, dynamic>>()) {
final String asset = fontFile['asset'] as String;
if (asset == null) {
- globals.printError('Warning: Missing asset in fonts for $familyName', emphasis: true);
+ _logger.printError('Warning: Missing asset in fonts for $familyName', emphasis: true);
continue;
}
@@ -310,16 +315,16 @@
}
@visibleForTesting
-String buildSchemaDir(FileSystem fs) {
- return globals.fs.path.join(
- globals.fs.path.absolute(Cache.flutterRoot), 'packages', 'flutter_tools', 'schema',
+String buildSchemaDir(FileSystem fileSystem) {
+ return fileSystem.path.join(
+ fileSystem.path.absolute(Cache.flutterRoot), 'packages', 'flutter_tools', 'schema',
);
}
@visibleForTesting
-String buildSchemaPath(FileSystem fs) {
- return globals.fs.path.join(
- buildSchemaDir(fs),
+String buildSchemaPath(FileSystem fileSystem) {
+ return fileSystem.path.join(
+ buildSchemaDir(fileSystem),
'pubspec_yaml.json',
);
}
@@ -327,7 +332,7 @@
/// This method should be kept in sync with the schema in
/// `$FLUTTER_ROOT/packages/flutter_tools/schema/pubspec_yaml.json`,
/// but avoid introducing dependencies on packages for simple validation.
-bool _validate(YamlMap manifest) {
+bool _validate(YamlMap manifest, Logger logger) {
final List<String> errors = <String>[];
for (final MapEntry<dynamic, dynamic> kvp in manifest.entries) {
if (kvp.key is! String) {
@@ -357,8 +362,8 @@
}
if (errors.isNotEmpty) {
- globals.printStatus('Error detected in pubspec.yaml:', emphasis: true);
- globals.printError(errors.join('\n'));
+ logger.printStatus('Error detected in pubspec.yaml:', emphasis: true);
+ logger.printError(errors.join('\n'));
return false;
}
diff --git a/packages/flutter_tools/lib/src/globals.dart b/packages/flutter_tools/lib/src/globals.dart
index 43a743b..5031e3e 100644
--- a/packages/flutter_tools/lib/src/globals.dart
+++ b/packages/flutter_tools/lib/src/globals.dart
@@ -43,7 +43,10 @@
OperatingSystemUtils get os => context.get<OperatingSystemUtils>();
PersistentToolState get persistentToolState => PersistentToolState.instance;
Usage get flutterUsage => context.get<Usage>();
-FlutterProjectFactory get projectFactory => context.get<FlutterProjectFactory>() ?? FlutterProjectFactory();
+FlutterProjectFactory get projectFactory => context.get<FlutterProjectFactory>() ?? FlutterProjectFactory(
+ logger: logger,
+ fileSystem: fs,
+);
const FileSystem _kLocalFs = LocalFileSystem();
diff --git a/packages/flutter_tools/lib/src/project.dart b/packages/flutter_tools/lib/src/project.dart
index 4efd7c5..9928c96 100644
--- a/packages/flutter_tools/lib/src/project.dart
+++ b/packages/flutter_tools/lib/src/project.dart
@@ -12,6 +12,7 @@
import 'artifacts.dart';
import 'base/common.dart';
import 'base/file_system.dart';
+import 'base/logger.dart';
import 'build_info.dart';
import 'bundle.dart' as bundle;
import 'features.dart';
@@ -24,7 +25,14 @@
import 'template.dart';
class FlutterProjectFactory {
- FlutterProjectFactory();
+ FlutterProjectFactory({
+ @required Logger logger,
+ @required FileSystem fileSystem,
+ }) : _logger = logger,
+ _fileSystem = fileSystem;
+
+ final Logger _logger;
+ final FileSystem _fileSystem;
@visibleForTesting
final Map<String, FlutterProject> projects =
@@ -34,14 +42,18 @@
/// if `pubspec.yaml` or `example/pubspec.yaml` is invalid.
FlutterProject fromDirectory(Directory directory) {
assert(directory != null);
- return projects.putIfAbsent(directory.path, /* ifAbsent */ () {
+ return projects.putIfAbsent(directory.path, () {
final FlutterManifest manifest = FlutterProject._readManifest(
directory.childFile(bundle.defaultManifestPath).path,
+ logger: _logger,
+ fileSystem: _fileSystem,
);
final FlutterManifest exampleManifest = FlutterProject._readManifest(
FlutterProject._exampleDirectory(directory)
.childFile(bundle.defaultManifestPath)
.path,
+ logger: _logger,
+ fileSystem: _fileSystem,
);
return FlutterProject(directory, manifest, exampleManifest);
});
@@ -167,7 +179,7 @@
FlutterProject get example => FlutterProject(
_exampleDirectory(directory),
_exampleManifest,
- FlutterManifest.empty(),
+ FlutterManifest.empty(logger: globals.logger),
);
/// True if this project is a Flutter module project.
@@ -187,13 +199,20 @@
///
/// Completes with an empty [FlutterManifest], if the file does not exist.
/// Completes with a ToolExit on validation error.
- static FlutterManifest _readManifest(String path) {
+ static FlutterManifest _readManifest(String path, {
+ @required Logger logger,
+ @required FileSystem fileSystem,
+ }) {
FlutterManifest manifest;
try {
- manifest = FlutterManifest.createFromPath(path);
+ manifest = FlutterManifest.createFromPath(
+ path,
+ logger: logger,
+ fileSystem: fileSystem,
+ );
} on YamlException catch (e) {
- globals.printStatus('Error detected in pubspec.yaml:', emphasis: true);
- globals.printError('$e');
+ logger.printStatus('Error detected in pubspec.yaml:', emphasis: true);
+ logger.printError('$e');
}
if (manifest == null) {
throwToolExit('Please correct the pubspec.yaml file at $path');
diff --git a/packages/flutter_tools/test/general.shard/flutter_manifest_test.dart b/packages/flutter_tools/test/general.shard/flutter_manifest_test.dart
index 81f98300..ace5077 100644
--- a/packages/flutter_tools/test/general.shard/flutter_manifest_test.dart
+++ b/packages/flutter_tools/test/general.shard/flutter_manifest_test.dart
@@ -2,54 +2,60 @@
// 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:file/file.dart';
import 'package:file/memory.dart';
-import 'package:flutter_tools/src/base/context.dart';
import 'package:flutter_tools/src/base/file_system.dart';
+import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/flutter_manifest.dart';
import '../src/common.dart';
import '../src/context.dart';
-import '../src/pubspec_schema.dart';
void main() {
setUpAll(() {
Cache.flutterRoot = getFlutterRoot();
});
- group('FlutterManifest', () {
- testUsingContext('is empty when the pubspec.yaml file is empty', () async {
- final FlutterManifest flutterManifest = FlutterManifest.createFromString('');
- expect(flutterManifest.isEmpty, true);
- expect(flutterManifest.appName, '');
- expect(flutterManifest.usesMaterialDesign, false);
- expect(flutterManifest.fontsDescriptor, isEmpty);
- expect(flutterManifest.fonts, isEmpty);
- expect(flutterManifest.assets, isEmpty);
- });
+ testWithoutContext('FlutterManifest is empty when the pubspec.yaml file is empty', () async {
+ final BufferLogger logger = BufferLogger.test();
+ final FlutterManifest flutterManifest = FlutterManifest.createFromString(
+ '',
+ logger: logger,
+ );
- test('has no fonts or assets when the "flutter" section is empty', () async {
- const String manifest = '''
+ expect(flutterManifest.isEmpty, true);
+ expect(flutterManifest.appName, '');
+ expect(flutterManifest.usesMaterialDesign, false);
+ expect(flutterManifest.fontsDescriptor, isEmpty);
+ expect(flutterManifest.fonts, isEmpty);
+ expect(flutterManifest.assets, isEmpty);
+ });
+
+ testWithoutContext('FlutterManifest has no fonts or assets when the "flutter" section is empty', () async {
+ const String manifest = '''
name: test
dependencies:
flutter:
sdk: flutter
''';
- final FlutterManifest flutterManifest = FlutterManifest.createFromString(manifest);
- expect(flutterManifest, isNotNull);
- expect(flutterManifest.isEmpty, false);
- expect(flutterManifest.appName, 'test');
- expect(flutterManifest.usesMaterialDesign, false);
- expect(flutterManifest.fontsDescriptor, isEmpty);
- expect(flutterManifest.fonts, isEmpty);
- expect(flutterManifest.assets, isEmpty);
- });
+ final BufferLogger logger = BufferLogger.test();
+ final FlutterManifest flutterManifest = FlutterManifest.createFromString(
+ manifest,
+ logger: logger,
+ );
- test('knows if material design is used', () async {
- const String manifest = '''
+ expect(flutterManifest, isNotNull);
+ expect(flutterManifest.isEmpty, false);
+ expect(flutterManifest.appName, 'test');
+ expect(flutterManifest.usesMaterialDesign, false);
+ expect(flutterManifest.fontsDescriptor, isEmpty);
+ expect(flutterManifest.fonts, isEmpty);
+ expect(flutterManifest.assets, isEmpty);
+ });
+
+ testWithoutContext('FlutterManifest knows if material design is used', () async {
+ const String manifest = '''
name: test
dependencies:
flutter:
@@ -57,12 +63,17 @@
flutter:
uses-material-design: true
''';
- final FlutterManifest flutterManifest = FlutterManifest.createFromString(manifest);
- expect(flutterManifest.usesMaterialDesign, true);
- });
+ final BufferLogger logger = BufferLogger.test();
+ final FlutterManifest flutterManifest = FlutterManifest.createFromString(
+ manifest,
+ logger: logger,
+ );
- test('has two assets', () async {
- const String manifest = '''
+ expect(flutterManifest.usesMaterialDesign, true);
+ });
+
+ testWithoutContext('FlutterManifest has two assets', () async {
+ const String manifest = '''
name: test
dependencies:
flutter:
@@ -73,14 +84,20 @@
- a/foo
- a/bar
''';
- final FlutterManifest flutterManifest = FlutterManifest.createFromString(manifest);
- expect(flutterManifest.assets.length, 2);
- expect(flutterManifest.assets[0], Uri.parse('a/foo'));
- expect(flutterManifest.assets[1], Uri.parse('a/bar'));
- });
+ final BufferLogger logger = BufferLogger.test();
+ final FlutterManifest flutterManifest = FlutterManifest.createFromString(
+ manifest,
+ logger: logger,
+ );
- test('has one font family with one asset', () async {
- const String manifest = '''
+ expect(flutterManifest.assets, <Uri>[
+ Uri.parse('a/foo'),
+ Uri.parse('a/bar'),
+ ]);
+ });
+
+ testWithoutContext('FlutterManifest has one font family with one asset', () async {
+ const String manifest = '''
name: test
dependencies:
flutter:
@@ -92,24 +109,29 @@
fonts:
- asset: a/bar
''';
- final FlutterManifest flutterManifest = FlutterManifest.createFromString(manifest);
- final dynamic expectedFontsDescriptor = [{'fonts': [{'asset': 'a/bar'}], 'family': 'foo'}]; // ignore: always_specify_types
- expect(flutterManifest.fontsDescriptor, expectedFontsDescriptor);
- final List<Font> fonts = flutterManifest.fonts;
- expect(fonts.length, 1);
- final Font font = fonts[0];
- final dynamic fooFontDescriptor = {'family': 'foo', 'fonts': [{'asset': 'a/bar'}]}; // ignore: always_specify_types
- expect(font.descriptor, fooFontDescriptor);
- expect(font.familyName, 'foo');
- final List<FontAsset> assets = font.fontAssets;
- expect(assets.length, 1);
- final FontAsset fontAsset = assets[0];
- expect(fontAsset.assetUri.path, 'a/bar');
- expect(fontAsset.weight, isNull);
- expect(fontAsset.style, isNull);
- });
+ final BufferLogger logger = BufferLogger.test();
+ final FlutterManifest flutterManifest = FlutterManifest.createFromString(
+ manifest,
+ logger: logger,
+ );
- test('has one font family with a simple asset and one with weight', () async {
+ expect(flutterManifest.fonts, hasLength(1));
+ expect(flutterManifest.fonts.single, matchesFont(
+ familyName: 'foo',
+ descriptor: <String, Object>{
+ 'family': 'foo',
+ 'fonts': <Object>[
+ <String, Object>{'asset': 'a/bar'},
+ ],
+ },
+ fontAssets: <Matcher>[
+ matchesFontAsset(assetUri: Uri.parse('a/bar')),
+ ],
+ ));
+ });
+
+ testWithoutContext('FlutterManifest has one font family with a simple asset '
+ 'and one with weight', () async {
const String manifest = '''
name: test
dependencies:
@@ -124,29 +146,32 @@
- asset: a/bar
weight: 400
''';
- final FlutterManifest flutterManifest = FlutterManifest.createFromString(manifest);
- final dynamic expectedFontsDescriptor = [{'fonts': [{'asset': 'a/bar'}, {'weight': 400, 'asset': 'a/bar'}], 'family': 'foo'}]; // ignore: always_specify_types
- expect(flutterManifest.fontsDescriptor, expectedFontsDescriptor);
- final List<Font> fonts = flutterManifest.fonts;
- expect(fonts.length, 1);
- final Font font = fonts[0];
- final dynamic fooFontDescriptor = {'family': 'foo', 'fonts': [{'asset': 'a/bar'}, {'weight': 400, 'asset': 'a/bar'}]}; // ignore: always_specify_types
- expect(font.descriptor, fooFontDescriptor);
- expect(font.familyName, 'foo');
- final List<FontAsset> assets = font.fontAssets;
- expect(assets.length, 2);
- final FontAsset fontAsset0 = assets[0];
- expect(fontAsset0.assetUri.path, 'a/bar');
- expect(fontAsset0.weight, isNull);
- expect(fontAsset0.style, isNull);
- final FontAsset fontAsset1 = assets[1];
- expect(fontAsset1.assetUri.path, 'a/bar');
- expect(fontAsset1.weight, 400);
- expect(fontAsset1.style, isNull);
- });
+ final BufferLogger logger = BufferLogger.test();
+ final FlutterManifest flutterManifest = FlutterManifest.createFromString(
+ manifest,
+ logger: logger,
+ );
- test('has one font family with a simple asset and one with weight and style', () async {
- const String manifest = '''
+ expect(flutterManifest.fonts, hasLength(1));
+ expect(flutterManifest.fonts.single, matchesFont(
+ familyName: 'foo',
+ descriptor: <String, Object>{
+ 'family': 'foo',
+ 'fonts': <Object>[
+ <String, Object>{'asset': 'a/bar'},
+ <String, Object>{'weight': 400, 'asset': 'a/bar'},
+ ],
+ },
+ fontAssets: <Matcher>[
+ matchesFontAsset(assetUri: Uri.parse('a/bar')),
+ matchesFontAsset(assetUri: Uri.parse('a/bar'), weight: 400),
+ ])
+ );
+ });
+
+ testWithoutContext('FlutterManifest has one font family with a simple asset '
+ 'and one with weight and style', () {
+ const String manifest = '''
name: test
dependencies:
flutter:
@@ -161,30 +186,32 @@
weight: 400
style: italic
''';
- final FlutterManifest flutterManifest = FlutterManifest.createFromString(manifest);
- final dynamic expectedFontsDescriptor = [{'fonts': [{'asset': 'a/bar'}, {'style': 'italic', 'weight': 400, 'asset': 'a/bar'}], 'family': 'foo'}]; // ignore: always_specify_types
+ final BufferLogger logger = BufferLogger.test();
+ final FlutterManifest flutterManifest = FlutterManifest.createFromString(
+ manifest,
+ logger: logger,
+ );
- expect(flutterManifest.fontsDescriptor, expectedFontsDescriptor);
- final List<Font> fonts = flutterManifest.fonts;
- expect(fonts.length, 1);
- final Font font = fonts[0];
- final dynamic fooFontDescriptor = {'family': 'foo', 'fonts': [{'asset': 'a/bar'}, {'weight': 400, 'style': 'italic', 'asset': 'a/bar'}]}; // ignore: always_specify_types
- expect(font.descriptor, fooFontDescriptor);
- expect(font.familyName, 'foo');
- final List<FontAsset> assets = font.fontAssets;
- expect(assets.length, 2);
- final FontAsset fontAsset0 = assets[0];
- expect(fontAsset0.assetUri.path, 'a/bar');
- expect(fontAsset0.weight, isNull);
- expect(fontAsset0.style, isNull);
- final FontAsset fontAsset1 = assets[1];
- expect(fontAsset1.assetUri.path, 'a/bar');
- expect(fontAsset1.weight, 400);
- expect(fontAsset1.style, 'italic');
- });
+ expect(flutterManifest.fonts, hasLength(1));
+ expect(flutterManifest.fonts.single, matchesFont(
+ familyName: 'foo',
+ descriptor: <String, Object>{
+ 'family': 'foo',
+ 'fonts': <Object>[
+ <String, Object>{'asset': 'a/bar'},
+ <String, Object>{'weight': 400, 'style': 'italic', 'asset': 'a/bar'},
+ ],
+ },
+ fontAssets: <Matcher>[
+ matchesFontAsset(assetUri: Uri.parse('a/bar')),
+ matchesFontAsset(assetUri: Uri.parse('a/bar'), weight: 400, style: 'italic'),
+ ],
+ ));
+ });
- test('has two font families, each with one simple asset and one with weight and style', () async {
- const String manifest = '''
+ testWithoutContext('FlutterManifest has two font families, each with one '
+ 'simple asset and one with weight and style', () {
+ const String manifest = '''
name: test
dependencies:
flutter:
@@ -205,48 +232,95 @@
asset: a/baz
style: italic
''';
- final FlutterManifest flutterManifest = FlutterManifest.createFromString(manifest);
- final dynamic expectedFontsDescriptor = <dynamic>[
- {'fonts': [{'asset': 'a/bar'}, {'style': 'italic', 'weight': 400, 'asset': 'a/bar'}], 'family': 'foo'}, // ignore: always_specify_types
- {'fonts': [{'asset': 'a/baz'}, {'style': 'italic', 'weight': 400, 'asset': 'a/baz'}], 'family': 'bar'}, // ignore: always_specify_types
- ];
- expect(flutterManifest.fontsDescriptor, expectedFontsDescriptor);
- final List<Font> fonts = flutterManifest.fonts;
- expect(fonts.length, 2);
+ final BufferLogger logger = BufferLogger.test();
+ final FlutterManifest flutterManifest = FlutterManifest.createFromString(
+ manifest,
+ logger: logger,
+ );
- final Font fooFont = fonts[0];
- final dynamic fooFontDescriptor = {'family': 'foo', 'fonts': [{'asset': 'a/bar'}, {'weight': 400, 'style': 'italic', 'asset': 'a/bar'}]}; // ignore: always_specify_types
- expect(fooFont.descriptor, fooFontDescriptor);
- expect(fooFont.familyName, 'foo');
- final List<FontAsset> fooAassets = fooFont.fontAssets;
- expect(fooAassets.length, 2);
- final FontAsset fooFontAsset0 = fooAassets[0];
- expect(fooFontAsset0.assetUri.path, 'a/bar');
- expect(fooFontAsset0.weight, isNull);
- expect(fooFontAsset0.style, isNull);
- final FontAsset fooFontAsset1 = fooAassets[1];
- expect(fooFontAsset1.assetUri.path, 'a/bar');
- expect(fooFontAsset1.weight, 400);
- expect(fooFontAsset1.style, 'italic');
+ expect(flutterManifest.fonts, hasLength(2));
+ expect(flutterManifest.fonts, containsAll(<Matcher>[
+ matchesFont(
+ familyName: 'foo',
+ descriptor: <String, Object>{
+ 'family': 'foo',
+ 'fonts': <Object>[
+ <String, Object>{'asset': 'a/bar'},
+ <String, Object>{'weight': 400, 'style': 'italic', 'asset': 'a/bar'},
+ ],
+ },
+ fontAssets: <Matcher>[
+ matchesFontAsset(assetUri: Uri.parse('a/bar')),
+ matchesFontAsset(assetUri: Uri.parse('a/bar'), weight: 400, style: 'italic'),
+ ],
+ ),
+ matchesFont(
+ familyName: 'bar',
+ descriptor: <String, Object>{
+ 'family': 'bar',
+ 'fonts': <Object>[
+ <String, Object>{'asset': 'a/baz'},
+ <String, Object>{'weight': 400, 'style': 'italic', 'asset': 'a/baz'},
+ ],
+ },
+ fontAssets: <Matcher>[
+ matchesFontAsset(assetUri: Uri.parse('a/baz')),
+ matchesFontAsset(assetUri: Uri.parse('a/baz'), weight: 400, style: 'italic'),
+ ],
+ ),
+ ]));
+ });
- final Font barFont = fonts[1];
- const String fontDescriptor = '{family: bar, fonts: [{asset: a/baz}, {weight: 400, style: italic, asset: a/baz}]}'; // ignore: always_specify_types
- 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.assetUri.path, 'a/baz');
- expect(barFontAsset0.weight, isNull);
- expect(barFontAsset0.style, isNull);
- final FontAsset barFontAsset1 = barAssets[1];
- expect(barFontAsset1.assetUri.path, 'a/baz');
- expect(barFontAsset1.weight, 400);
- expect(barFontAsset1.style, 'italic');
- });
+ testWithoutContext('FlutterManifest.fontsDescriptor combines descriptors from '
+ 'individual fonts', () {
+ const 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 BufferLogger logger = BufferLogger.test();
+ final FlutterManifest flutterManifest = FlutterManifest.createFromString(
+ manifest,
+ logger: logger,
+ );
- testUsingContext('has only one of two font families when one declaration is missing the "family" option', () async {
- const String manifest = '''
+ expect(flutterManifest.fontsDescriptor, <Object>[
+ <String, Object>{
+ 'family': 'foo',
+ 'fonts': <Object>[
+ <String, Object>{'asset': 'a/bar'},
+ <String, Object>{'weight': 400, 'style': 'italic', 'asset': 'a/bar'},
+ ],
+ },
+ <String, Object>{
+ 'family': 'bar',
+ 'fonts': <Object>[
+ <String, Object>{'asset': 'a/baz'},
+ <String, Object>{'weight': 400, 'style': 'italic', 'asset': 'a/baz'},
+ ],
+ },
+ ]);
+ });
+
+ testWithoutContext('FlutterManifest has only one of two font families when '
+ 'one declaration is missing the "family" option', () async {
+ const String manifest = '''
name: test
dependencies:
flutter:
@@ -266,30 +340,34 @@
weight: 400
style: italic
''';
- final FlutterManifest flutterManifest = FlutterManifest.createFromString(manifest);
+ final BufferLogger logger = BufferLogger.test();
+ final FlutterManifest flutterManifest = FlutterManifest.createFromString(
+ manifest,
+ logger: logger,
+ );
- final dynamic expectedFontsDescriptor = [{'fonts': [{'asset': 'a/bar'}, {'style': 'italic', 'weight': 400, 'asset': 'a/bar'}], 'family': 'foo'}]; // ignore: always_specify_types
- expect(flutterManifest.fontsDescriptor, expectedFontsDescriptor);
- final List<Font> fonts = flutterManifest.fonts;
- expect(fonts.length, 1);
- final Font fooFont = fonts[0];
- final dynamic fooFontDescriptor = {'family': 'foo', 'fonts': [{'asset': 'a/bar'}, {'weight': 400, 'style': 'italic', 'asset': 'a/bar'}]}; // ignore: always_specify_types
- expect(fooFont.descriptor, fooFontDescriptor);
- expect(fooFont.familyName, 'foo');
- final List<FontAsset> fooAassets = fooFont.fontAssets;
- expect(fooAassets.length, 2);
- final FontAsset fooFontAsset0 = fooAassets[0];
- expect(fooFontAsset0.assetUri.path, 'a/bar');
- expect(fooFontAsset0.weight, isNull);
- expect(fooFontAsset0.style, isNull);
- final FontAsset fooFontAsset1 = fooAassets[1];
- expect(fooFontAsset1.assetUri.path, 'a/bar');
- expect(fooFontAsset1.weight, 400);
- expect(fooFontAsset1.style, 'italic');
- });
+ expect(flutterManifest.fonts, hasLength(1));
+ expect(flutterManifest.fonts, containsAll(<Matcher>[
+ matchesFont(
+ familyName: 'foo',
+ descriptor: <String, Object>{
+ 'family': 'foo',
+ 'fonts': <Object>[
+ <String, Object>{'asset': 'a/bar'},
+ <String, Object>{'weight': 400, 'style': 'italic', 'asset': 'a/bar'},
+ ],
+ },
+ fontAssets: <Matcher>[
+ matchesFontAsset(assetUri: Uri.parse('a/bar')),
+ matchesFontAsset(assetUri: Uri.parse('a/bar'), weight: 400, style: 'italic'),
+ ],
+ ),
+ ]));
+ });
- testUsingContext('has only one of two font families when one declaration is missing the "fonts" option', () async {
- const String manifest = '''
+ testWithoutContext('FlutterManifest has only one of two font families when '
+ 'one declaration is missing the "fonts" option', () async {
+ const String manifest = '''
name: test
dependencies:
flutter:
@@ -305,29 +383,34 @@
style: italic
- family: bar
''';
- final FlutterManifest flutterManifest = FlutterManifest.createFromString(manifest);
- final dynamic expectedFontsDescriptor = [{'fonts': [{'asset': 'a/bar'}, {'style': 'italic', 'weight': 400, 'asset': 'a/bar'}], 'family': 'foo'}]; // ignore: always_specify_types
- expect(flutterManifest.fontsDescriptor, expectedFontsDescriptor);
- final List<Font> fonts = flutterManifest.fonts;
- expect(fonts.length, 1);
- final Font fooFont = fonts[0];
- final dynamic fooFontDescriptor = {'family': 'foo', 'fonts': [{'asset': 'a/bar'}, {'weight': 400, 'style': 'italic', 'asset': 'a/bar'}]}; // ignore: always_specify_types
- expect(fooFont.descriptor, fooFontDescriptor);
- expect(fooFont.familyName, 'foo');
- final List<FontAsset> fooAassets = fooFont.fontAssets;
- expect(fooAassets.length, 2);
- final FontAsset fooFontAsset0 = fooAassets[0];
- expect(fooFontAsset0.assetUri.path, 'a/bar');
- expect(fooFontAsset0.weight, isNull);
- expect(fooFontAsset0.style, isNull);
- final FontAsset fooFontAsset1 = fooAassets[1];
- expect(fooFontAsset1.assetUri.path, 'a/bar');
- expect(fooFontAsset1.weight, 400);
- expect(fooFontAsset1.style, 'italic');
- });
+ final BufferLogger logger = BufferLogger.test();
+ final FlutterManifest flutterManifest = FlutterManifest.createFromString(
+ manifest,
+ logger: logger,
+ );
- testUsingContext('has no font family when declaration is missing the "asset" option', () async {
- const String manifest = '''
+ expect(flutterManifest.fonts, hasLength(1));
+ expect(flutterManifest.fonts, containsAll(<Matcher>[
+ matchesFont(
+ familyName: 'foo',
+ descriptor: <String, Object>{
+ 'family': 'foo',
+ 'fonts': <Object>[
+ <String, Object>{'asset': 'a/bar'},
+ <String, Object>{'weight': 400, 'style': 'italic', 'asset': 'a/bar'},
+ ],
+ },
+ fontAssets: <Matcher>[
+ matchesFontAsset(assetUri: Uri.parse('a/bar')),
+ matchesFontAsset(assetUri: Uri.parse('a/bar'), weight: 400, style: 'italic'),
+ ],
+ ),
+ ]));
+ });
+
+ testWithoutContext('FlutterManifest has no font family when declaration is '
+ 'missing the "asset" option', () async {
+ const String manifest = '''
name: test
dependencies:
flutter:
@@ -339,57 +422,76 @@
fonts:
- weight: 400
''';
- final FlutterManifest flutterManifest = FlutterManifest.createFromString(manifest);
+ final BufferLogger logger = BufferLogger.test();
+ final FlutterManifest flutterManifest = FlutterManifest.createFromString(
+ manifest,
+ logger: logger,
+ );
- expect(flutterManifest.fontsDescriptor, <dynamic>[]);
- final List<Font> fonts = flutterManifest.fonts;
- expect(fonts.length, 0);
- });
+ expect(flutterManifest.fontsDescriptor, isEmpty);
+ expect(flutterManifest.fonts, isEmpty);
+ });
- test('allows a blank flutter section', () async {
- const String manifest = '''
+ testWithoutContext('FlutterManifest allows a blank flutter section', () {
+ const String manifest = '''
name: test
dependencies:
flutter:
sdk: flutter
flutter:
''';
- final FlutterManifest flutterManifest = FlutterManifest.createFromString(manifest);
- expect(flutterManifest.isEmpty, false);
- expect(flutterManifest.isModule, false);
- expect(flutterManifest.isPlugin, false);
- expect(flutterManifest.androidPackage, null);
- expect(flutterManifest.usesAndroidX, false);
- });
+ final BufferLogger logger = BufferLogger.test();
+ final FlutterManifest flutterManifest = FlutterManifest.createFromString(
+ manifest,
+ logger: logger,
+ );
- test('allows a module declaration', () async {
- const String manifest = '''
+ expect(flutterManifest.isEmpty, false);
+ expect(flutterManifest.isModule, false);
+ expect(flutterManifest.isPlugin, false);
+ expect(flutterManifest.androidPackage, null);
+ expect(flutterManifest.usesAndroidX, false);
+ });
+
+ testWithoutContext('FlutterManifest allows a module declaration', () {
+ const String manifest = '''
name: test
flutter:
module:
androidPackage: com.example
androidX: true
''';
- final FlutterManifest flutterManifest = FlutterManifest.createFromString(manifest);
- expect(flutterManifest.isModule, true);
- expect(flutterManifest.androidPackage, 'com.example');
- expect(flutterManifest.usesAndroidX, true);
- });
+ final BufferLogger logger = BufferLogger.test();
+ final FlutterManifest flutterManifest = FlutterManifest.createFromString(
+ manifest,
+ logger: logger,
+ );
- test('allows a legacy plugin declaration', () async {
- const String manifest = '''
+ expect(flutterManifest.isModule, true);
+ expect(flutterManifest.androidPackage, 'com.example');
+ expect(flutterManifest.usesAndroidX, true);
+ });
+
+ testWithoutContext('FlutterManifest allows a legacy plugin declaration', () {
+ const String manifest = '''
name: test
flutter:
plugin:
androidPackage: com.example
''';
- final FlutterManifest flutterManifest = FlutterManifest.createFromString(manifest);
- expect(flutterManifest.isPlugin, true);
- expect(flutterManifest.androidPackage, 'com.example');
- });
+ final BufferLogger logger = BufferLogger.test();
+ final FlutterManifest flutterManifest = FlutterManifest.createFromString(
+ manifest,
+ logger: logger,
+ );
- test('allows a multi-plat plugin declaration with android only', () async {
- const String manifest = '''
+ expect(flutterManifest.isPlugin, true);
+ expect(flutterManifest.androidPackage, 'com.example');
+ });
+
+ testWithoutContext('FlutterManifest allows a multi-plat plugin declaration '
+ 'with android only', () {
+ const String manifest = '''
name: test
flutter:
plugin:
@@ -398,13 +500,19 @@
package: com.example
pluginClass: TestPlugin
''';
- final FlutterManifest flutterManifest = FlutterManifest.createFromString(manifest);
- expect(flutterManifest.isPlugin, true);
- expect(flutterManifest.androidPackage, 'com.example');
- });
+ final BufferLogger logger = BufferLogger.test();
+ final FlutterManifest flutterManifest = FlutterManifest.createFromString(
+ manifest,
+ logger: logger,
+ );
- test('allows a multi-plat plugin declaration with ios only', () async {
- const String manifest = '''
+ expect(flutterManifest.isPlugin, true);
+ expect(flutterManifest.androidPackage, 'com.example');
+ });
+
+ testWithoutContext('FlutterManifest allows a multi-plat plugin declaration '
+ 'with ios only', () {
+ const String manifest = '''
name: test
flutter:
plugin:
@@ -412,37 +520,35 @@
ios:
pluginClass: HelloPlugin
''';
- final FlutterManifest flutterManifest = FlutterManifest.createFromString(manifest);
- expect(flutterManifest.isPlugin, true);
- expect(flutterManifest.androidPackage, isNull);
- });
+ final BufferLogger logger = BufferLogger.test();
+ final FlutterManifest flutterManifest = FlutterManifest.createFromString(
+ manifest,
+ logger: logger,
+ );
- testUsingContext('handles an invalid plugin declaration', () async {
- const String manifest = '''
+ expect(flutterManifest.isPlugin, true);
+ expect(flutterManifest.androidPackage, isNull);
+ });
+
+ testUsingContext('FlutterManifest handles an invalid plugin declaration', () {
+ const String manifest = '''
name: test
flutter:
plugin:
''';
- final FlutterManifest flutterManifest = FlutterManifest.createFromString(manifest);
- expect(flutterManifest, null);
- expect(testLogger.errorText, contains('Expected "plugin" to be an object, but got null'));
- });
+ final BufferLogger logger = BufferLogger.test();
+ final FlutterManifest flutterManifest = FlutterManifest.createFromString(
+ manifest,
+ logger: logger,
+ );
+ expect(flutterManifest, null);
+ expect(logger.errorText,
+ contains('Expected "plugin" to be an object, but got null'));
+ });
- Future<void> checkManifestVersion({
- String manifest,
- String expectedAppVersion,
- String expectedBuildName,
- String expectedBuildNumber,
- }) async {
- final FlutterManifest flutterManifest = FlutterManifest.createFromString(manifest);
- expect(flutterManifest.appVersion, expectedAppVersion);
- expect(flutterManifest.buildName, expectedBuildName);
- expect(flutterManifest.buildNumber, expectedBuildNumber);
- }
-
- test('parses major.minor.patch+build version clause 1', () async {
- const String manifest = '''
+ testWithoutContext('FlutterManifest parses major.minor.patch+build version clause 1', () {
+ const String manifest = '''
name: test
version: 1.0.0+2
dependencies:
@@ -450,16 +556,21 @@
sdk: flutter
flutter:
''';
- await checkManifestVersion(
- manifest: manifest,
- expectedAppVersion: '1.0.0+2',
- expectedBuildName: '1.0.0',
- expectedBuildNumber: '2',
- );
- });
+ final BufferLogger logger = BufferLogger.test();
+ final FlutterManifest flutterManifest = FlutterManifest.createFromString(
+ manifest,
+ logger: logger,
+ );
- test('parses major.minor.patch with no build version', () async {
- const String manifest = '''
+ expect(flutterManifest, matchesManifest(
+ appVersion: '1.0.0+2',
+ buildName: '1.0.0',
+ buildNumber: '2'),
+ );
+ });
+
+ testWithoutContext('FlutterManifest parses major.minor.patch with no build version', () {
+ const String manifest = '''
name: test
version: 0.0.1
dependencies:
@@ -467,16 +578,21 @@
sdk: flutter
flutter:
''';
- await checkManifestVersion(
- manifest: manifest,
- expectedAppVersion: '0.0.1',
- expectedBuildName: '0.0.1',
- expectedBuildNumber: null,
- );
- });
+ final BufferLogger logger = BufferLogger.test();
+ final FlutterManifest flutterManifest = FlutterManifest.createFromString(
+ manifest,
+ logger: logger,
+ );
- test('parses major.minor.patch+build version clause 2', () async {
- const String manifest = '''
+ expect(flutterManifest, matchesManifest(
+ appVersion: '0.0.1',
+ buildName: '0.0.1',
+ buildNumber: null),
+ );
+ });
+
+ testWithoutContext('FlutterManifest parses major.minor.patch+build version clause 2', () {
+ const String manifest = '''
name: test
version: 1.0.0-beta+exp.sha.5114f85
dependencies:
@@ -484,16 +600,21 @@
sdk: flutter
flutter:
''';
- await checkManifestVersion(
- manifest: manifest,
- expectedAppVersion: '1.0.0-beta+exp.sha.5114f85',
- expectedBuildName: '1.0.0-beta',
- expectedBuildNumber: 'exp.sha.5114f85',
- );
- });
+ final BufferLogger logger = BufferLogger.test();
+ final FlutterManifest flutterManifest = FlutterManifest.createFromString(
+ manifest,
+ logger: logger,
+ );
- test('parses major.minor+build version clause', () async {
- const String manifest = '''
+ expect(flutterManifest, matchesManifest(
+ appVersion: '1.0.0-beta+exp.sha.5114f85',
+ buildName: '1.0.0-beta',
+ buildNumber: 'exp.sha.5114f85'),
+ );
+ });
+
+ testWithoutContext('FlutterManifest parses major.minor+build version clause', () {
+ const String manifest = '''
name: test
version: 1.0+2
dependencies:
@@ -501,16 +622,21 @@
sdk: flutter
flutter:
''';
- await checkManifestVersion(
- manifest: manifest,
- expectedAppVersion: '1.0+2',
- expectedBuildName: '1.0',
- expectedBuildNumber: '2',
- );
- });
+ final BufferLogger logger = BufferLogger.test();
+ final FlutterManifest flutterManifest = FlutterManifest.createFromString(
+ manifest,
+ logger: logger,
+ );
- test('parses empty version clause', () async {
- const String manifest = '''
+ expect(flutterManifest, matchesManifest(
+ appVersion: '1.0+2',
+ buildName: '1.0',
+ buildNumber: '2'),
+ );
+ });
+
+ testWithoutContext('FlutterManifest parses empty version clause', () {
+ const String manifest = '''
name: test
version:
dependencies:
@@ -518,33 +644,43 @@
sdk: flutter
flutter:
''';
- await checkManifestVersion(
- manifest: manifest,
- expectedAppVersion: null,
- expectedBuildName: null,
- expectedBuildNumber: null,
- );
- });
+ final BufferLogger logger = BufferLogger.test();
+ final FlutterManifest flutterManifest = FlutterManifest.createFromString(
+ manifest,
+ logger: logger,
+ );
- test('parses no version clause', () async {
- const String manifest = '''
+ expect(flutterManifest, matchesManifest(
+ appVersion: null,
+ buildName: null,
+ buildNumber: null),
+ );
+ });
+
+ testWithoutContext('FlutterManifest parses no version clause', () {
+ const String manifest = '''
name: test
dependencies:
flutter:
sdk: flutter
flutter:
''';
- await checkManifestVersion(
- manifest: manifest,
- expectedAppVersion: null,
- expectedBuildName: null,
- expectedBuildNumber: null,
- );
- });
+ final BufferLogger logger = BufferLogger.test();
+ final FlutterManifest flutterManifest = FlutterManifest.createFromString(
+ manifest,
+ logger: logger,
+ );
+
+ expect(flutterManifest, matchesManifest(
+ appVersion: null,
+ buildName: null,
+ buildNumber: null),
+ );
+ });
// Regression test for https://github.com/flutter/flutter/issues/31764
- testUsingContext('Returns proper error when font detail is malformed', () async {
- const String manifest = '''
+ testWithoutContext('FlutterManifest returns proper error when font detail is malformed', () {
+ const String manifest = '''
name: test
dependencies:
flutter:
@@ -555,14 +691,20 @@
fonts:
-asset: a/bar
''';
- final FlutterManifest flutterManifest = FlutterManifest.createFromString(manifest);
+ final BufferLogger logger = BufferLogger.test();
+ final FlutterManifest flutterManifest = FlutterManifest.createFromString(
+ manifest,
+ logger: logger,
+ );
- expect(flutterManifest, null);
- expect(testLogger.errorText, contains('Expected "fonts" to either be null or a list.'));
- });
+ expect(flutterManifest, null);
+ expect(logger.errorText,
+ contains('Expected "fonts" to either be null or a list.'));
+ });
- testUsingContext('Returns proper error when font detail is not a list of maps', () async {
- const String manifest = '''
+ testWithoutContext('FlutterManifest returns proper error when font detail is '
+ 'not a list of maps', () {
+ const String manifest = '''
name: test
dependencies:
flutter:
@@ -573,14 +715,20 @@
fonts:
- asset
''';
- final FlutterManifest flutterManifest = FlutterManifest.createFromString(manifest);
+ final BufferLogger logger = BufferLogger.test();
+ final FlutterManifest flutterManifest = FlutterManifest.createFromString(
+ manifest,
+ logger: logger,
+ );
- expect(flutterManifest, null);
- expect(testLogger.errorText, contains('Expected "fonts" to be a list of maps.'));
- });
+ expect(flutterManifest, null);
+ expect(logger.errorText,
+ contains('Expected "fonts" to be a list of maps.'));
+ });
- testUsingContext('Returns proper error when font is a map instead of a list', () async {
- const String manifest = '''
+ testWithoutContext('FlutterManifest returns proper error when font is a map '
+ 'instead of a list', () {
+ const String manifest = '''
name: test
dependencies:
flutter:
@@ -591,14 +739,19 @@
fonts:
-asset: a/bar
''';
- final FlutterManifest flutterManifest = FlutterManifest.createFromString(manifest);
+ final BufferLogger logger = BufferLogger.test();
+ final FlutterManifest flutterManifest = FlutterManifest.createFromString(
+ manifest,
+ logger: logger,
+ );
- expect(flutterManifest, null);
- expect(testLogger.errorText, contains('Expected "fonts" to be a list'));
- });
+ expect(flutterManifest, null);
+ expect(logger.errorText, contains('Expected "fonts" to be a list'));
+ });
- testUsingContext('Returns proper error when second font family is invalid', () async {
- const String manifest = '''
+ testWithoutContext('FlutterManifest returns proper error when second font '
+ 'family is invalid', () {
+ const String manifest = '''
name: test
dependencies:
flutter:
@@ -611,13 +764,18 @@
- asset: a/bar
- string
''';
- final FlutterManifest flutterManifest = FlutterManifest.createFromString(manifest);
- expect(flutterManifest, null);
- expect(testLogger.errorText, contains('Expected a map.'));
- });
+ final BufferLogger logger = BufferLogger.test();
+ final FlutterManifest flutterManifest = FlutterManifest.createFromString(
+ manifest,
+ logger: logger,
+ );
- testUsingContext('Does not crash on empty entry', () async {
- const String manifest = '''
+ expect(flutterManifest, null);
+ expect(logger.errorText, contains('Expected a map.'));
+ });
+
+ testWithoutContext('FlutterManifest does not crash on empty entry', () {
+ const String manifest = '''
name: test
dependencies:
flutter:
@@ -628,15 +786,19 @@
- lib/gallery/example_code.dart
-
''';
- final FlutterManifest flutterManifest = FlutterManifest.createFromString(manifest);
- final List<Uri> assets = flutterManifest.assets;
+ final BufferLogger logger = BufferLogger.test();
+ final FlutterManifest flutterManifest = FlutterManifest.createFromString(
+ manifest,
+ logger: logger,
+ );
+ final List<Uri> assets = flutterManifest.assets;
- expect(testLogger.errorText, contains('Asset manifest contains a null or empty uri.'));
- expect(assets.length, 1);
- });
+ expect(logger.errorText, contains('Asset manifest contains a null or empty uri.'));
+ expect(assets, hasLength(1));
+ });
- testUsingContext('Special characters in asset URIs', () async {
- const String manifest = '''
+ testWithoutContext('FlutterManifest handles special characters in asset URIs', () {
+ const String manifest = '''
name: test
dependencies:
flutter:
@@ -648,17 +810,24 @@
- lib/gallery/abc?xyz
- lib/gallery/aaa bbb
''';
- final FlutterManifest flutterManifest = FlutterManifest.createFromString(manifest);
- final List<Uri> assets = flutterManifest.assets;
+ final BufferLogger logger = BufferLogger.test();
+ final FlutterManifest flutterManifest = FlutterManifest.createFromString(
+ manifest,
+ logger: logger,
+ );
+ final List<Uri> assets = flutterManifest.assets;
- expect(assets.length, 3);
- expect(assets[0].path, 'lib/gallery/abc%23xyz');
- expect(assets[1].path, 'lib/gallery/abc%3Fxyz');
- expect(assets[2].path, 'lib/gallery/aaa%20bbb');
- });
+ expect(assets, hasLength(3));
+ expect(assets, <Uri>[
+ Uri.parse('lib/gallery/abc%23xyz'),
+ Uri.parse('lib/gallery/abc%3Fxyz'),
+ Uri.parse('lib/gallery/aaa%20bbb'),
+ ]);
+ });
- testUsingContext('Returns proper error when flutter is a list instead of a map', () async {
- const String manifest = '''
+ testWithoutContext('FlutterManifest returns proper error when flutter is a '
+ 'list instead of a map', () {
+ const String manifest = '''
name: test
dependencies:
flutter:
@@ -666,16 +835,43 @@
flutter:
- uses-material-design: true
''';
- final FlutterManifest flutterManifest = FlutterManifest.createFromString(manifest);
+ final BufferLogger logger = BufferLogger.test();
+ final FlutterManifest flutterManifest = FlutterManifest.createFromString(
+ manifest,
+ logger: logger,
+ );
- expect(flutterManifest, null);
- expect(testLogger.errorText, contains('Expected "flutter" section to be an object or null, but got [{uses-material-design: true}].'));
- });
+ expect(flutterManifest, null);
+ expect(logger.errorText,
+ contains(
+ 'Expected "flutter" section to be an object or null, but got '
+ '[{uses-material-design: true}].',
+ ),
+ );
});
- group('FlutterManifest with MemoryFileSystem', () {
- Future<void> assertSchemaIsReadable() async {
- const String manifest = '''
+ testWithoutContext('FlutterManifest can parse manifest on posix filesystem', () {
+ const String manifest = '''
+name: test
+dependencies:
+ flutter:
+ sdk: flutter
+flutter:
+''';
+ final FileSystem fileSystem = MemoryFileSystem.test();
+ fileSystem.file('pubspec.yaml').writeAsStringSync(manifest);
+ final BufferLogger logger = BufferLogger.test();
+ final FlutterManifest flutterManifest = FlutterManifest.createFromPath(
+ 'pubspec.yaml',
+ fileSystem: fileSystem,
+ logger: logger,
+ );
+
+ expect(flutterManifest.isEmpty, false);
+ });
+
+ testWithoutContext('FlutterManifest can parse manifest on windows filesystem', () {
+ const String manifest = '''
name: test
dependencies:
flutter:
@@ -683,47 +879,48 @@
flutter:
''';
- final FlutterManifest flutterManifest = FlutterManifest.createFromString(manifest);
- expect(flutterManifest.isEmpty, false);
- }
-
- void testUsingContextAndFs(
- String description,
- FileSystem filesystem,
- dynamic testMethod(),
- ) {
- testUsingContext(
- description,
- () async {
- writeEmptySchemaFile(filesystem);
- testMethod();
- },
- overrides: <Type, Generator>{
- FileSystem: () => filesystem,
- ProcessManager: () => FakeProcessManager.any(),
- },
- );
- }
-
- testUsingContext('Validate manifest on original fs', () {
- assertSchemaIsReadable();
- });
-
- testUsingContextAndFs(
- 'Validate manifest on Posix FS',
- MemoryFileSystem(style: FileSystemStyle.posix),
- () {
- assertSchemaIsReadable();
- },
+ final FileSystem fileSystem = MemoryFileSystem.test(style: FileSystemStyle.windows);
+ fileSystem.file('pubspec.yaml').writeAsStringSync(manifest);
+ final BufferLogger logger = BufferLogger.test();
+ final FlutterManifest flutterManifest = FlutterManifest.createFromPath(
+ 'pubspec.yaml',
+ fileSystem: fileSystem,
+ logger: logger,
);
- testUsingContextAndFs(
- 'Validate manifest on Windows FS',
- MemoryFileSystem(style: FileSystemStyle.windows),
- () {
- assertSchemaIsReadable();
- },
- );
-
+ expect(flutterManifest.isEmpty, false);
});
}
+
+Matcher matchesManifest({
+ String appVersion,
+ String buildName,
+ String buildNumber,
+}) {
+ return isA<FlutterManifest>()
+ .having((FlutterManifest manifest) => manifest.appVersion, 'appVersion', appVersion)
+ .having((FlutterManifest manifest) => manifest.buildName, 'buildName', buildName)
+ .having((FlutterManifest manifest) => manifest.buildNumber, 'buildNumber', buildNumber);
+}
+
+Matcher matchesFontAsset({
+ Uri assetUri,
+ int weight,
+ String style,
+}) {
+ return isA<FontAsset>()
+ .having((FontAsset fontAsset) => fontAsset.assetUri, 'assetUri', assetUri)
+ .having((FontAsset fontAsset) => fontAsset.weight, 'weight', weight)
+ .having((FontAsset fontAsset) => fontAsset.style, 'style', style);
+}
+
+Matcher matchesFont({
+ Map<String, Object> descriptor,
+ String familyName,
+ List<Matcher> fontAssets,
+}) {
+ return isA<Font>()
+ .having((Font font) => font.descriptor, 'descriptor', descriptor)
+ .having((Font font) => font.familyName, 'familyName', familyName)
+ .having((Font font) => font.fontAssets, 'fontAssets', containsAll(fontAssets));
+}
diff --git a/packages/flutter_tools/test/general.shard/github_template_test.dart b/packages/flutter_tools/test/general.shard/github_template_test.dart
index b5142c1..1082d51 100644
--- a/packages/flutter_tools/test/general.shard/github_template_test.dart
+++ b/packages/flutter_tools/test/general.shard/github_template_test.dart
@@ -160,7 +160,10 @@
fileSystem: fs,
logger: logger,
client: SuccessShortenURLFakeHttpClient(),
- flutterProjectFactory: FlutterProjectFactory(),
+ flutterProjectFactory: FlutterProjectFactory(
+ fileSystem: fs,
+ logger: logger,
+ ),
);
expect(
await creator.toolCrashIssueTemplateGitHubURL(command, error, stackTrace, doctorText),
@@ -176,7 +179,10 @@
fileSystem: fs,
logger: logger,
client: FakeHttpClient(),
- flutterProjectFactory: FlutterProjectFactory(),
+ flutterProjectFactory: FlutterProjectFactory(
+ fileSystem: fs,
+ logger: logger,
+ ),
);
expect(
await creator.toolCrashIssueTemplateGitHubURL(command, error, stackTrace, doctorText),
@@ -199,7 +205,10 @@
fileSystem: fs,
logger: logger,
client: FakeHttpClient(),
- flutterProjectFactory: FlutterProjectFactory(),
+ flutterProjectFactory: FlutterProjectFactory(
+ fileSystem: fs,
+ logger: logger,
+ ),
);
final Directory projectDirectory = fs.currentDirectory;
diff --git a/packages/flutter_tools/test/general.shard/project_test.dart b/packages/flutter_tools/test/general.shard/project_test.dart
index 1647480..b212434 100644
--- a/packages/flutter_tools/test/general.shard/project_test.dart
+++ b/packages/flutter_tools/test/general.shard/project_test.dart
@@ -8,6 +8,7 @@
import 'package:file/memory.dart';
import 'package:flutter_tools/src/base/context.dart';
import 'package:flutter_tools/src/base/file_system.dart';
+import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/features.dart';
import 'package:flutter_tools/src/flutter_manifest.dart';
@@ -23,6 +24,10 @@
import '../src/testbed.dart';
void main() {
+ // TODO(jonahwilliams): remove once FlutterProject is fully refactored.
+ // this is safe since no tests have expectations on the test logger.
+ final BufferLogger logger = BufferLogger.test();
+
group('Project', () {
group('construction', () {
testInMemory('fails on null directory', () async {
@@ -154,8 +159,8 @@
testInMemory('does nothing, if project is not created', () async {
final FlutterProject project = FlutterProject(
globals.fs.directory('not_created'),
- FlutterManifest.empty(),
- FlutterManifest.empty(),
+ FlutterManifest.empty(logger: logger),
+ FlutterManifest.empty(logger: logger),
);
await project.ensureReadyForPlatformSpecificTooling();
expectNotExists(project.directory);
@@ -197,7 +202,10 @@
FileSystem: () => MemoryFileSystem(),
ProcessManager: () => FakeProcessManager.any(),
FeatureFlags: () => TestFeatureFlags(isMacOSEnabled: true),
- FlutterProjectFactory: () => FlutterProjectFactory(),
+ FlutterProjectFactory: () => FlutterProjectFactory(
+ logger: logger,
+ fileSystem: globals.fs,
+ ),
});
testUsingContext('generates Xcode configuration for macOS', () async {
final FlutterProject project = await someProject();
@@ -208,7 +216,10 @@
FileSystem: () => MemoryFileSystem(),
ProcessManager: () => FakeProcessManager.any(),
FeatureFlags: () => TestFeatureFlags(isMacOSEnabled: true),
- FlutterProjectFactory: () => FlutterProjectFactory(),
+ FlutterProjectFactory: () => FlutterProjectFactory(
+ logger: logger,
+ fileSystem: globals.fs,
+ ),
});
testUsingContext('injects plugins for Linux', () async {
final FlutterProject project = await someProject();
@@ -220,7 +231,10 @@
FileSystem: () => MemoryFileSystem(),
ProcessManager: () => FakeProcessManager.any(),
FeatureFlags: () => TestFeatureFlags(isLinuxEnabled: true),
- FlutterProjectFactory: () => FlutterProjectFactory(),
+ FlutterProjectFactory: () => FlutterProjectFactory(
+ logger: logger,
+ fileSystem: globals.fs,
+ ),
});
testUsingContext('injects plugins for Windows', () async {
final FlutterProject project = await someProject();
@@ -246,7 +260,10 @@
FileSystem: () => MemoryFileSystem(),
ProcessManager: () => FakeProcessManager.any(),
FeatureFlags: () => TestFeatureFlags(isWindowsEnabled: true),
- FlutterProjectFactory: () => FlutterProjectFactory(),
+ FlutterProjectFactory: () => FlutterProjectFactory(
+ logger: logger,
+ fileSystem: globals.fs,
+ ),
});
testInMemory('creates Android library in module', () async {
final FlutterProject project = await aModuleProject();
@@ -312,7 +329,10 @@
setUp(() {
fs = MemoryFileSystem();
mockXcodeProjectInterpreter = MockXcodeProjectInterpreter();
- flutterProjectFactory = FlutterProjectFactory();
+ flutterProjectFactory = FlutterProjectFactory(
+ logger: logger,
+ fileSystem: fs,
+ );
});
testInMemory('default host app language', () async {
@@ -348,7 +368,10 @@
fs = MemoryFileSystem();
mockPlistUtils = MockPlistUtils();
mockXcodeProjectInterpreter = MockXcodeProjectInterpreter();
- flutterProjectFactory = FlutterProjectFactory();
+ flutterProjectFactory = FlutterProjectFactory(
+ fileSystem: fs,
+ logger: logger,
+ );
});
void testWithMocks(String description, Future<void> testMethod()) {
@@ -521,8 +544,12 @@
FlutterProjectFactory flutterProjectFactory;
setUp(() {
- testbed = Testbed();
- flutterProjectFactory = FlutterProjectFactory();
+ testbed = Testbed(setup: () {
+ flutterProjectFactory = FlutterProjectFactory(
+ fileSystem: globals.fs,
+ logger: globals.logger,
+ );
+ });
});
test('Handles asking for builders from an invalid pubspec', () => testbed.run(() {
@@ -646,7 +673,10 @@
packagesFile.createSync(recursive: true);
packagesFile.writeAsStringSync('flutter_template_images:${dummyTemplateImagesDirectory.uri}');
- final FlutterProjectFactory flutterProjectFactory = FlutterProjectFactory();
+ final FlutterProjectFactory flutterProjectFactory = FlutterProjectFactory(
+ fileSystem: testFileSystem,
+ logger: globals.logger ?? BufferLogger.test(),
+ );
testUsingContext(
description,
diff --git a/packages/flutter_tools/test/src/android_common.dart b/packages/flutter_tools/test/src/android_common.dart
index 01eec17..cba857f 100644
--- a/packages/flutter_tools/test/src/android_common.dart
+++ b/packages/flutter_tools/test/src/android_common.dart
@@ -4,6 +4,7 @@
import 'package:meta/meta.dart';
+import 'package:flutter_tools/src/globals.dart' as globals;
import 'package:flutter_tools/src/android/android_builder.dart';
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/build_info.dart';
@@ -39,7 +40,11 @@
/// within [directoryOverride].
class FakeFlutterProjectFactory extends FlutterProjectFactory {
FakeFlutterProjectFactory(this.directoryOverride) :
- assert(directoryOverride != null);
+ assert(directoryOverride != null),
+ super(
+ fileSystem: globals.fs,
+ logger: globals.logger,
+ );
final Directory directoryOverride;