From 267737a74d288d6a75da5a49746d3d8c8daf0f9a Mon Sep 17 00:00:00 2001 From: p-mazhnik Date: Tue, 2 Aug 2022 21:14:40 +0300 Subject: [PATCH 1/3] fix loading config from pubspec.yaml --- lib/main.dart | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 50ed76c9cd..75a58d678e 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -181,11 +181,9 @@ Map? loadConfigFileFromArgResults(ArgResults argResults, {bool return loadConfigFile(defaultConfigFile, fileOptionResult); } catch (e) { // Try pubspec.yaml for compatibility - if (configFile == null) { - try { - return loadConfigFile('pubspec.yaml', fileOptionResult); - } catch (_) {} - } + try { + return loadConfigFile('pubspec.yaml', fileOptionResult); + } catch (_) {} // if nothing got returned, print error if (verbose) { From 284d0b5bd68584fa1f44d5e7fa30ad4a24ab9156 Mon Sep 17 00:00:00 2001 From: p-mazhnik Date: Wed, 3 Aug 2022 13:13:06 +0300 Subject: [PATCH 2/3] refactor package to use FlutterLauncherIconsConfig --- lib/android.dart | 57 +++--- lib/flutter_launcher_icons_config.dart | 32 +++- lib/flutter_launcher_icons_config.g.dart | 2 +- lib/ios.dart | 14 +- lib/main.dart | 167 ++++-------------- test/abs/icon_generator_test.mocks.dart | 37 +++- test/android_test.dart | 20 ++- test/flutter_launcher_icons_config_test.dart | 26 ++- test/main_test.dart | 70 ++++---- .../windows_icon_generator_test.mocks.dart | 45 ++++- 10 files changed, 243 insertions(+), 227 deletions(-) diff --git a/lib/android.dart b/lib/android.dart index 39a96df9a1..5682a7d8df 100644 --- a/lib/android.dart +++ b/lib/android.dart @@ -1,4 +1,6 @@ import 'dart:io'; +import 'package:flutter_launcher_icons/constants.dart'; +import 'package:flutter_launcher_icons/flutter_launcher_icons_config.dart'; import 'package:flutter_launcher_icons/utils.dart'; import 'package:flutter_launcher_icons/xml_templates.dart' as xml_template; import 'package:image/image.dart'; @@ -29,17 +31,21 @@ List androidIcons = [ AndroidIconTemplate(directoryName: 'mipmap-xxxhdpi', size: 192), ]; -void createDefaultIcons(Map flutterLauncherIconsConfig, String? flavor) { +void createDefaultIcons(FlutterLauncherIconsConfig flutterLauncherIconsConfig, String? flavor) { printStatus('Creating default icons Android'); - final String filePath = getAndroidIconPath(flutterLauncherIconsConfig); + // todo: support prefixPath + final String? filePath = flutterLauncherIconsConfig.getImagePathAndroid(); + if (filePath == null) { + throw const InvalidConfigException(errorMissingImagePath); + } final Image? image = decodeImageFile(filePath); if (image == null) { return; } final File androidManifestFile = File(constants.androidManifestFile); - if (isCustomAndroidFile(flutterLauncherIconsConfig)) { + if (flutterLauncherIconsConfig.isCustomAndroidFile) { printStatus('Adding a new Android launcher icon'); - final String iconName = getNewIconName(flutterLauncherIconsConfig); + final String iconName = flutterLauncherIconsConfig.android; isAndroidIconNameCorrectFormat(iconName); final String iconPath = '$iconName.png'; for (AndroidIconTemplate template in androidIcons) { @@ -64,12 +70,15 @@ bool isAndroidIconNameCorrectFormat(String iconName) { return true; } -void createAdaptiveIcons(Map flutterLauncherIconsConfig, String? flavor) { +void createAdaptiveIcons(FlutterLauncherIconsConfig flutterLauncherIconsConfig, String? flavor) { printStatus('Creating adaptive icons Android'); // Retrieve the necessary Flutter Launcher Icons configuration from the pubspec.yaml file - final String backgroundConfig = flutterLauncherIconsConfig['adaptive_icon_background']; - final String foregroundImagePath = flutterLauncherIconsConfig['adaptive_icon_foreground']; + final String? backgroundConfig = flutterLauncherIconsConfig.adaptiveIconBackground; + final String? foregroundImagePath = flutterLauncherIconsConfig.adaptiveIconForeground; + if (backgroundConfig == null || foregroundImagePath == null) { + throw const InvalidConfigException(errorMissingImagePath); + } final Image? foregroundImage = decodeImageFile(foregroundImagePath); if (foregroundImage == null) { return; @@ -110,9 +119,9 @@ void updateColorsXmlFile(String backgroundConfig, String? flavor) { /// Creates the xml file required for the adaptive launcher icon /// FILE LOCATED HERE: res/mipmap-anydpi/{icon-name-from-yaml-config}.xml -void createAdaptiveIconMipmapXmlFile(Map flutterLauncherIconsConfig, String? flavor) { - if (isCustomAndroidFile(flutterLauncherIconsConfig)) { - File(constants.androidAdaptiveXmlFolder(flavor) + getNewIconName(flutterLauncherIconsConfig) + '.xml') +void createAdaptiveIconMipmapXmlFile(FlutterLauncherIconsConfig flutterLauncherIconsConfig, String? flavor) { + if (flutterLauncherIconsConfig.isCustomAndroidFile) { + File(constants.androidAdaptiveXmlFolder(flavor) + flutterLauncherIconsConfig.android + '.xml') .create(recursive: true) .then((File adaptiveIcon) { adaptiveIcon.writeAsString(xml_template.icLauncherXml); @@ -128,7 +137,7 @@ void createAdaptiveIconMipmapXmlFile(Map flutterLauncherIconsCo /// creates adaptive background using png image void _createAdaptiveBackgrounds( - Map yamlConfig, + FlutterLauncherIconsConfig flutterLauncherIconsConfig, String adaptiveIconBackgroundImagePath, String? flavor, ) { @@ -146,8 +155,8 @@ void _createAdaptiveBackgrounds( // Creates the xml file required for the adaptive launcher icon // FILE LOCATED HERE: res/mipmap-anydpi/{icon-name-from-yaml-config}.xml - if (isCustomAndroidFile(yamlConfig)) { - File(constants.androidAdaptiveXmlFolder(flavor) + getNewIconName(yamlConfig) + '.xml') + if (flutterLauncherIconsConfig.isCustomAndroidFile) { + File(constants.androidAdaptiveXmlFolder(flavor) + flutterLauncherIconsConfig.android + '.xml') .create(recursive: true) .then((File adaptiveIcon) { adaptiveIcon.writeAsString(xml_template.icLauncherDrawableBackgroundXml); @@ -194,19 +203,6 @@ void updateColorsFile(File colorsFile, String backgroundColor) { colorsFile.writeAsStringSync(lines.join('\n')); } -/// Check to see if specified Android config is a string or bool -/// String - Generate new launcher icon with the string specified -/// bool - override the default flutter project icon -bool isCustomAndroidFile(Map config) { - final dynamic androidConfig = config['android']; - return androidConfig is String; -} - -/// return the new launcher icon file name -String getNewIconName(Map config) { - return config['android']; -} - /// Overrides the existing launcher icons in the project /// Note: Do not change interpolation unless you end up with better results (see issue for result when using cubic /// interpolation) @@ -271,7 +267,7 @@ List _transformAndroidManifestWithNewLauncherIcon(List oldManife /// - build.gradle: `'android/app/build.gradle'` /// - local.properties: `'android/local.properties'` /// -/// If found none returns 0 +/// If found none returns [constants.androidDefaultAndroidMinSDK] int minSdk() { final androidGradleFile = File(constants.androidGradleFile); final androidLocalPropertiesFile = File(constants.androidLocalPropertiesFile); @@ -346,13 +342,6 @@ int? _getMinSdkFlutterGradle(File localPropertiesFile) { return null; } -/// Method for the retrieval of the Android icon path -/// If image_path_android is found, this will be prioritised over the image_path -/// value. -String getAndroidIconPath(Map config) { - return config['image_path_android'] ?? config['image_path']; -} - /// Returns true if the adaptive icon configuration is a PNG image bool isAdaptiveIconConfigPngFile(String backgroundFile) { return backgroundFile.endsWith('.png'); diff --git a/lib/flutter_launcher_icons_config.dart b/lib/flutter_launcher_icons_config.dart index b5baa3f862..92c5084e23 100644 --- a/lib/flutter_launcher_icons_config.dart +++ b/lib/flutter_launcher_icons_config.dart @@ -47,7 +47,7 @@ class FlutterLauncherIconsConfig { final int minSdkAndroid; /// IOS remove_alpha_ios - @JsonKey(name: 'remove_alpha_ios', defaultValue: true) + @JsonKey(name: 'remove_alpha_ios') final bool removeAlphaIOS; /// Web platform config @@ -68,7 +68,7 @@ class FlutterLauncherIconsConfig { this.adaptiveIconForeground, this.adaptiveIconBackground, this.minSdkAndroid = constants.androidDefaultAndroidMinSDK, - this.removeAlphaIOS = true, + this.removeAlphaIOS = false, this.webConfig, this.windowsConfig, }); @@ -136,6 +136,34 @@ class FlutterLauncherIconsConfig { @override String toString() => 'FlutterLauncherIconsConfig: ${toJson()}'; + + bool get isNeedingNewIOSIcon => ios != false; + bool get isNeedingNewAndroidIcon => android != false; + bool get hasAndroidAdaptiveConfig => + isNeedingNewAndroidIcon && + adaptiveIconForeground != null && + adaptiveIconBackground != null; + + // todo: refactor after Android & iOS configs will be refactored to the new schema + // https://github.com/fluttercommunity/flutter_launcher_icons/issues/394 + String? getImagePathIOS() => imagePathIOS ?? imagePath; + + /// Method for the retrieval of the Android icon path + /// If image_path_android is found, this will be prioritised over the image_path + /// value. + String? getImagePathAndroid() => imagePathAndroid ?? imagePath; + + /// Check to see if specified Android config is a string or bool + /// String - Generate new launcher icon with the string specified + /// bool - override the default flutter project icon + bool get isCustomAndroidFile => android is String; + + /// Checks if contains any platform config + bool get hasPlatformConfig => + ios != false || + android != false || + webConfig != null || + windowsConfig != null; } /// Parse `web` config from `flutter_launcher_icons.yaml` diff --git a/lib/flutter_launcher_icons_config.g.dart b/lib/flutter_launcher_icons_config.g.dart index 13881e7d9e..4c70f82115 100644 --- a/lib/flutter_launcher_icons_config.g.dart +++ b/lib/flutter_launcher_icons_config.g.dart @@ -25,7 +25,7 @@ FlutterLauncherIconsConfig _$FlutterLauncherIconsConfigFromJson(Map json) => minSdkAndroid: $checkedConvert('min_sdk_android', (v) => v as int? ?? 21), removeAlphaIOS: - $checkedConvert('remove_alpha_ios', (v) => v as bool? ?? true), + $checkedConvert('remove_alpha_ios', (v) => v as bool? ?? false), webConfig: $checkedConvert( 'web', (v) => v == null ? null : WebConfig.fromJson(v as Map)), windowsConfig: $checkedConvert('windows', diff --git a/lib/ios.dart b/lib/ios.dart index 67fe290d3e..11fe8e4dad 100644 --- a/lib/ios.dart +++ b/lib/ios.dart @@ -1,5 +1,7 @@ import 'dart:convert'; import 'dart:io'; +import 'package:flutter_launcher_icons/custom_exceptions.dart'; +import 'package:flutter_launcher_icons/flutter_launcher_icons_config.dart'; import 'package:flutter_launcher_icons/utils.dart'; import 'package:image/image.dart'; import 'package:flutter_launcher_icons/constants.dart'; @@ -36,22 +38,26 @@ List iosIcons = [ IosIconTemplate(name: '-1024x1024@1x', size: 1024), ]; -void createIcons(Map config, String? flavor) { - final String filePath = config['image_path_ios'] ?? config['image_path']; +void createIcons(FlutterLauncherIconsConfig config, String? flavor) { + // todo: support prefixPath + final String? filePath = config.getImagePathIOS(); + if (filePath == null) { + throw const InvalidConfigException(errorMissingImagePath); + } // decodeImageFile shows error message if null // so can return here if image is null final Image? image = decodeImage(File(filePath).readAsBytesSync()); if (image == null) { return; } - if (config['remove_alpha_ios'] is bool && config['remove_alpha_ios']) { + if (config.removeAlphaIOS) { image.channels = Channels.rgb; } if (image.channels == Channels.rgba) { print('\nWARNING: Icons with alpha channel are not allowed in the Apple App Store.\nSet "remove_alpha_ios: true" to remove it.\n'); } String iconName; - final dynamic iosConfig = config['ios']; + final dynamic iosConfig = config.ios; if (flavor != null) { final String catalogName = 'AppIcon-$flavor'; printStatus('Building iOS launcher icon for $flavor'); diff --git a/lib/main.dart b/lib/main.dart index 75a58d678e..31db89907d 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -9,7 +9,6 @@ import 'package:flutter_launcher_icons/custom_exceptions.dart'; import 'package:flutter_launcher_icons/flutter_launcher_icons_config.dart'; import 'package:flutter_launcher_icons/ios.dart' as ios_launcher_icons; import 'package:flutter_launcher_icons/logger.dart'; -import 'package:flutter_launcher_icons/pubspec_parser.dart'; import 'package:flutter_launcher_icons/web/web_icon_generator.dart'; import 'package:flutter_launcher_icons/windows/windows_icon_generator.dart'; import 'package:path/path.dart' as path; @@ -21,9 +20,6 @@ const String prefixOption = 'prefix'; const String defaultConfigFile = 'flutter_launcher_icons.yaml'; const String flavorConfigFilePattern = r'^flutter_launcher_icons-(.*).yaml$'; -/// todo: remove this as it is moved to utils.dart -String flavorConfigFile(String flavor) => 'flutter_launcher_icons-$flavor.yaml'; - List getFlavors() { final List flavors = []; for (var item in Directory('.').listSync()) { @@ -68,26 +64,21 @@ Future createIconsFromArguments(List arguments) async { final flavors = getFlavors(); final hasFlavors = flavors.isNotEmpty; - // Load the config file - final Map? yamlConfig = loadConfigFileFromArgResults(argResults, verbose: true); final String prefixPath = argResults[prefixOption]; - // Load configs from given file(defaults to ./flutter_launcher_icons.yaml) or from ./pubspec.yaml - - final flutterLauncherIconsConfigs = - FlutterLauncherIconsConfig.loadConfigFromPath(argResults[fileOption], prefixPath) ?? - FlutterLauncherIconsConfig.loadConfigFromPubSpec(prefixPath); - if (yamlConfig == null || flutterLauncherIconsConfigs == null) { - throw NoConfigFoundException( - 'No configuration found in $defaultConfigFile or in ${constants.pubspecFilePath}. ' - 'In case file exists in different directory use --file option', - ); - } - // Create icons if (!hasFlavors) { + // Load configs from given file(defaults to ./flutter_launcher_icons.yaml) or from ./pubspec.yaml + + final flutterLauncherIconsConfigs = loadConfigFileFromArgResults(argResults); + if (flutterLauncherIconsConfigs == null) { + throw NoConfigFoundException( + 'No configuration found in $defaultConfigFile or in ${constants.pubspecFilePath}. ' + 'In case file exists in different directory use --file option', + ); + } try { - await createIconsFromConfig(yamlConfig, flutterLauncherIconsConfigs, logger, prefixPath); + await createIconsFromConfig(flutterLauncherIconsConfigs, logger, prefixPath); print('\n✓ Successfully generated launcher icons'); } catch (e) { stderr.writeln('\n✕ Could not generate launcher icons'); @@ -98,8 +89,13 @@ Future createIconsFromArguments(List arguments) async { try { for (String flavor in flavors) { print('\nFlavor: $flavor'); - final Map yamlConfig = loadConfigFile(flavorConfigFile(flavor), flavorConfigFile(flavor)); - await createIconsFromConfig(yamlConfig, flutterLauncherIconsConfigs, logger, prefixPath, flavor); + final flutterLauncherIconsConfigs = FlutterLauncherIconsConfig.loadConfigFromFlavor(flavor, prefixPath); + if (flutterLauncherIconsConfigs == null) { + throw NoConfigFoundException( + 'No configuration found for $flavor flavor.', + ); + } + await createIconsFromConfig(flutterLauncherIconsConfigs, logger, prefixPath, flavor); } print('\n✓ Successfully generated launcher icons for flavors'); } catch (e) { @@ -111,37 +107,23 @@ Future createIconsFromArguments(List arguments) async { } Future createIconsFromConfig( - Map config, FlutterLauncherIconsConfig flutterConfigs, FLILogger logger, String prefixPath, [ String? flavor, ]) async { - if (!isImagePathInConfig(config)) { - throw const InvalidConfigException(errorMissingImagePath); - } - if (!hasPlatformConfig(config)) { + if (!flutterConfigs.hasPlatformConfig) { throw const InvalidConfigException(errorMissingPlatform); } - if (isNeedingNewAndroidIcon(config) || hasAndroidAdaptiveConfig(config)) { - final int minSdk = config['min_sdk_android'] ?? android_launcher_icons.minSdk(); - if (minSdk == 0) { - throw const InvalidConfigException(errorMissingMinSdk); - } - if (minSdk < 26 && hasAndroidAdaptiveConfig(config) && !hasAndroidConfig(config)) { - throw const InvalidConfigException(errorMissingRegularAndroid); - } + if (flutterConfigs.isNeedingNewAndroidIcon) { + android_launcher_icons.createDefaultIcons(flutterConfigs, flavor); } - - if (isNeedingNewAndroidIcon(config)) { - android_launcher_icons.createDefaultIcons(config, flavor); - } - if (hasAndroidAdaptiveConfig(config)) { - android_launcher_icons.createAdaptiveIcons(config, flavor); + if (flutterConfigs.hasAndroidAdaptiveConfig) { + android_launcher_icons.createAdaptiveIcons(flutterConfigs, flavor); } - if (isNeedingNewIOSIcon(config)) { - ios_launcher_icons.createIcons(config, flavor); + if (flutterConfigs.isNeedingNewIOSIcon) { + ios_launcher_icons.createIcons(flutterConfigs, flavor); } // Generates Icons for given platform @@ -158,99 +140,10 @@ Future createIconsFromConfig( ); } -Map? loadConfigFileFromArgResults(ArgResults argResults, {bool verbose = false}) { - final String? configFile = argResults[fileOption]; - final String? fileOptionResult = argResults[fileOption]; - - // if icon is given, try to load icon - if (configFile != null && configFile != defaultConfigFile) { - try { - return loadConfigFile(configFile, fileOptionResult); - } catch (e) { - if (verbose) { - stderr.writeln(e); - } - - return null; - } - } - - // If none set try flutter_launcher_icons.yaml first then pubspec.yaml - // for compatibility - try { - return loadConfigFile(defaultConfigFile, fileOptionResult); - } catch (e) { - // Try pubspec.yaml for compatibility - try { - return loadConfigFile('pubspec.yaml', fileOptionResult); - } catch (_) {} - - // if nothing got returned, print error - if (verbose) { - stderr.writeln(e); - } - } - - return null; -} - -Map loadConfigFile(String path, String? fileOptionResult) { - final yamlMap = PubspecParser.fromPathToMap(path); - - if (yamlMap['flutter_icons'] is! Map) { - stderr.writeln(NoConfigFoundException('Check that your config file ' - '`${fileOptionResult ?? defaultConfigFile}`' - ' has a `flutter_icons` section')); - exit(1); - } - - // yamlMap has the type YamlMap, which has several unwanted sideeffects - final Map config = {}; - for (MapEntry entry in yamlMap['flutter_icons'].entries) { - config[entry.key] = entry.value; - } - - return config; -} - -bool isImagePathInConfig(Map flutterIconsConfig) { - return flutterIconsConfig.containsKey('image_path') || - (flutterIconsConfig.containsKey('image_path_android') && flutterIconsConfig.containsKey('image_path_ios')) || - flutterIconsConfig.containsKey('web'); -} - -bool hasPlatformConfig(Map flutterIconsConfig) { - return hasAndroidConfig(flutterIconsConfig) || hasIOSConfig(flutterIconsConfig) || hasWebConfig(flutterIconsConfig); -} - -bool hasAndroidConfig(Map flutterLauncherIcons) { - return flutterLauncherIcons.containsKey('android'); -} - -bool isNeedingNewAndroidIcon(Map flutterLauncherIconsConfig) { - return hasAndroidConfig(flutterLauncherIconsConfig) && flutterLauncherIconsConfig['android'] != false; -} - -bool hasAndroidAdaptiveConfig(Map flutterLauncherIconsConfig) { - return isNeedingNewAndroidIcon(flutterLauncherIconsConfig) && - flutterLauncherIconsConfig.containsKey('adaptive_icon_background') && - flutterLauncherIconsConfig.containsKey('adaptive_icon_foreground'); -} - -bool hasIOSConfig(Map flutterLauncherIconsConfig) { - return flutterLauncherIconsConfig.containsKey('ios'); -} - -bool isNeedingNewIOSIcon(Map flutterLauncherIconsConfig) { - return hasIOSConfig(flutterLauncherIconsConfig) && flutterLauncherIconsConfig['ios'] != false; -} - -/// Checks if the [flutterLauncherIconsConfig] contains web configs -bool hasWebConfig(Map flutterLauncherIconsConfig) { - return flutterLauncherIconsConfig.containsKey('web'); -} - -/// Checks if we should generate icons for web platform -bool isNeddingNewWebIcons(Map flutterLauncherIconsConfig) { - return hasWebConfig(flutterLauncherIconsConfig) && flutterLauncherIconsConfig['web'] != false; +FlutterLauncherIconsConfig? loadConfigFileFromArgResults(ArgResults argResults) { + final String prefixPath = argResults[prefixOption]; + final flutterLauncherIconsConfigs = + FlutterLauncherIconsConfig.loadConfigFromPath(argResults[fileOption], prefixPath) ?? + FlutterLauncherIconsConfig.loadConfigFromPubSpec(prefixPath); + return flutterLauncherIconsConfigs; } diff --git a/test/abs/icon_generator_test.mocks.dart b/test/abs/icon_generator_test.mocks.dart index b69e2a2d26..1ed38cfdb2 100644 --- a/test/abs/icon_generator_test.mocks.dart +++ b/test/abs/icon_generator_test.mocks.dart @@ -1,7 +1,8 @@ -// Mocks generated by Mockito 5.2.0 from annotations +// Mocks generated by Mockito 5.3.0 from annotations // in flutter_launcher_icons/test/abs/icon_generator_test.dart. // Do not manually edit this file. +// ignore_for_file: no_leading_underscores_for_library_prefixes import 'package:flutter_launcher_icons/abs/icon_generator.dart' as _i2; import 'package:flutter_launcher_icons/flutter_launcher_icons_config.dart' as _i3; @@ -16,9 +17,13 @@ import 'package:mockito/mockito.dart' as _i1; // ignore_for_file: prefer_const_constructors // ignore_for_file: unnecessary_parenthesis // ignore_for_file: camel_case_types +// ignore_for_file: subtype_of_sealed_class -class _FakeIconGeneratorContext_0 extends _i1.Fake - implements _i2.IconGeneratorContext {} +class _FakeIconGeneratorContext_0 extends _i1.SmartFake + implements _i2.IconGeneratorContext { + _FakeIconGeneratorContext_0(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); +} /// A class which mocks [FlutterLauncherIconsConfig]. /// @@ -38,6 +43,26 @@ class MockFlutterLauncherIconsConfig extends _i1.Mock .noSuchMethod(Invocation.getter(#removeAlphaIOS), returnValue: false) as bool); @override + bool get isNeedingNewIOSIcon => + (super.noSuchMethod(Invocation.getter(#isNeedingNewIOSIcon), + returnValue: false) as bool); + @override + bool get isNeedingNewAndroidIcon => + (super.noSuchMethod(Invocation.getter(#isNeedingNewAndroidIcon), + returnValue: false) as bool); + @override + bool get hasAndroidAdaptiveConfig => + (super.noSuchMethod(Invocation.getter(#hasAndroidAdaptiveConfig), + returnValue: false) as bool); + @override + bool get isCustomAndroidFile => + (super.noSuchMethod(Invocation.getter(#isCustomAndroidFile), + returnValue: false) as bool); + @override + bool get hasPlatformConfig => + (super.noSuchMethod(Invocation.getter(#hasPlatformConfig), + returnValue: false) as bool); + @override Map toJson() => (super.noSuchMethod(Invocation.method(#toJson, []), returnValue: {}) as Map); @@ -53,8 +78,10 @@ class MockIconGenerator extends _i1.Mock implements _i2.IconGenerator { @override _i2.IconGeneratorContext get context => (super.noSuchMethod( - Invocation.getter(#context), - returnValue: _FakeIconGeneratorContext_0()) as _i2.IconGeneratorContext); + Invocation.getter(#context), + returnValue: + _FakeIconGeneratorContext_0(this, Invocation.getter(#context))) + as _i2.IconGeneratorContext); @override String get platformName => (super.noSuchMethod(Invocation.getter(#platformName), returnValue: '') diff --git a/test/android_test.dart b/test/android_test.dart index eae4d65676..685e55e22b 100644 --- a/test/android_test.dart +++ b/test/android_test.dart @@ -2,6 +2,7 @@ import 'dart:io'; import 'package:flutter_launcher_icons/android.dart' as android; import 'package:flutter_launcher_icons/constants.dart'; +import 'package:flutter_launcher_icons/flutter_launcher_icons_config.dart'; import 'package:test/test.dart'; // unit tests for android.dart @@ -31,14 +32,22 @@ void main() { 'android': true, 'ios': true }; - expect(android.isCustomAndroidFile(flutterIconsConfig), false); + expect( + FlutterLauncherIconsConfig.fromJson(flutterIconsConfig) + .isCustomAndroidFile, + false, + ); final Map flutterIconsNewIconConfig = { 'image_path': 'assets/images/icon-710x599.png', 'android': 'New Icon', 'ios': true }; - expect(android.isCustomAndroidFile(flutterIconsNewIconConfig), true); + expect( + FlutterLauncherIconsConfig.fromJson(flutterIconsNewIconConfig) + .isCustomAndroidFile, + true, + ); }); test('Prioritise image_path_android over image_path', () { @@ -48,8 +57,11 @@ void main() { 'android': 'New Icon', 'ios': true }; - expect(android.getAndroidIconPath(flutterIconsNewIconConfig), - 'assets/images/icon-android.png'); + expect( + FlutterLauncherIconsConfig.fromJson(flutterIconsNewIconConfig) + .getImagePathAndroid(), + 'assets/images/icon-android.png', + ); }); test('Transforming manifest without icon must add icon', () async { diff --git a/test/flutter_launcher_icons_config_test.dart b/test/flutter_launcher_icons_config_test.dart index 1198682a08..2d2c9df8ba 100644 --- a/test/flutter_launcher_icons_config_test.dart +++ b/test/flutter_launcher_icons_config_test.dart @@ -75,7 +75,31 @@ void main() { ); }); }); - + group('#loadConfigFromTestPubSpec', () { + test('should return valid configs', () { + const String path = 'test/config/test_pubspec.yaml'; + final configs = FlutterLauncherIconsConfig.loadConfigFromPath(path, '.'); + expect(configs, isNotNull); + const String imagePath = 'assets/images/icon-710x599.png'; + expect(configs!.imagePath, imagePath); + // android configs + expect(configs.android, isTrue); + expect(configs.imagePathAndroid, isNull); + expect(configs.getImagePathAndroid(), imagePath); + expect(configs.adaptiveIconBackground, isNull); + expect(configs.adaptiveIconForeground, isNull); + expect(configs.minSdkAndroid, equals(21)); + // ios configs + expect(configs.ios, isTrue); + expect(configs.imagePathIOS, isNull); + expect(configs.getImagePathIOS(), imagePath); + expect(configs.removeAlphaIOS, isFalse); + // web configs + expect(configs.webConfig, isNull); + // windows + expect(configs.windowsConfig, isNull); + }); + }); group('#loadConfigFromPubSpec', () { setUpAll(() async { await d.dir('fli_test', [ diff --git a/test/main_test.dart b/test/main_test.dart index ccdd9db93b..346a7cf3ff 100644 --- a/test/main_test.dart +++ b/test/main_test.dart @@ -2,6 +2,7 @@ import 'dart:io'; import 'package:args/args.dart'; import 'package:flutter_launcher_icons/android.dart' as android; +import 'package:flutter_launcher_icons/flutter_launcher_icons_config.dart'; import 'package:flutter_launcher_icons/ios.dart' as ios; import 'package:flutter_launcher_icons/main.dart' show defaultConfigFile; import 'package:flutter_launcher_icons/main.dart' as main_dart; @@ -24,16 +25,15 @@ void main() { expect(ios.createImageList('blah').length, 25); }); - test('pubspec.yaml file exists', () async { - const String path = 'test/config/test_pubspec.yaml'; - final Map config = main_dart.loadConfigFile(path, null); - expect(config.length, isNotNull); - }); - group('config file from args', () { // Create mini parser with only the wanted option, mocking the real one final ArgParser parser = ArgParser() - ..addOption(main_dart.fileOption, abbr: 'f'); + ..addOption(main_dart.fileOption, abbr: 'f', defaultsTo: defaultConfigFile) + ..addOption( + main_dart.prefixOption, + abbr: 'p', + defaultsTo: '.', + ); final String testDir = join('.dart_tool', 'flutter_launcher_icons', 'test', 'config_file'); @@ -58,10 +58,10 @@ flutter_icons: ios: false '''); final ArgResults argResults = parser.parse([]); - final Map? config = + final FlutterLauncherIconsConfig? config = main_dart.loadConfigFileFromArgResults(argResults); expect(config, isNotNull); - expect(config!['android'], true); + expect(config!.android, true); }); test('default_use_pubspec', () async { await setCurrentDirectory('pubspec_only'); @@ -71,14 +71,14 @@ flutter_icons: ios: false '''); ArgResults argResults = parser.parse([]); - final Map? config = + final FlutterLauncherIconsConfig? config = main_dart.loadConfigFileFromArgResults(argResults); expect(config, isNotNull); - expect(config!['ios'], false); + expect(config!.ios, false); - // fails if forcing default file + // read pubspec if provided file is not found argResults = parser.parse(['-f', defaultConfigFile]); - expect(main_dart.loadConfigFileFromArgResults(argResults), isNull); + expect(main_dart.loadConfigFileFromArgResults(argResults), isNotNull); }); test('custom', () async { @@ -90,10 +90,10 @@ flutter_icons: '''); // if no argument set, should fail ArgResults argResults = parser.parse(['-f', 'custom.yaml']); - final Map? config = + final FlutterLauncherIconsConfig? config = main_dart.loadConfigFileFromArgResults(argResults); expect(config, isNotNull); - expect(config!['ios'], true); + expect(config!.ios, true); // should fail if no argument argResults = parser.parse([]); @@ -105,32 +105,32 @@ flutter_icons: }); }); - test('Incorrect pubspec.yaml path throws correct error message', () async { - const String incorrectPath = 'test/config/test_pubspec.yam'; - expect(() => main_dart.loadConfigFile(incorrectPath, null), - throwsA(const TypeMatcher())); - }); - test('image_path is in config', () { final Map flutterIconsConfig = { 'image_path': 'assets/images/icon-710x599.png', 'android': true, 'ios': true }; - expect(main_dart.isImagePathInConfig(flutterIconsConfig), true); + final config = FlutterLauncherIconsConfig.fromJson(flutterIconsConfig); + expect(config.getImagePathAndroid(), 'assets/images/icon-710x599.png'); + expect(config.getImagePathIOS(), 'assets/images/icon-710x599.png'); final Map flutterIconsConfigAndroid = { 'image_path_android': 'assets/images/icon-710x599.png', 'android': true, 'ios': true }; - expect(main_dart.isImagePathInConfig(flutterIconsConfigAndroid), false); + final configAndroid = FlutterLauncherIconsConfig.fromJson(flutterIconsConfigAndroid); + expect(configAndroid.getImagePathAndroid(), 'assets/images/icon-710x599.png'); + expect(configAndroid.getImagePathIOS(), isNull); final Map flutterIconsConfigBoth = { - 'image_path_android': 'assets/images/icon-710x599.png', - 'image_path_ios': 'assets/images/icon-710x599.png', + 'image_path_android': 'assets/images/icon-android.png', + 'image_path_ios': 'assets/images/icon-ios.png', 'android': true, 'ios': true }; - expect(main_dart.isImagePathInConfig(flutterIconsConfigBoth), true); + final configBoth = FlutterLauncherIconsConfig.fromJson(flutterIconsConfigBoth); + expect(configBoth.getImagePathAndroid(), 'assets/images/icon-android.png'); + expect(configBoth.getImagePathIOS(), 'assets/images/icon-ios.png'); }); test('At least one platform is in config file', () { @@ -139,14 +139,16 @@ flutter_icons: 'android': true, 'ios': true }; - expect(main_dart.hasPlatformConfig(flutterIconsConfig), true); + final config = FlutterLauncherIconsConfig.fromJson(flutterIconsConfig); + expect(config.hasPlatformConfig, true); }); test('No platform specified in config', () { final Map flutterIconsConfig = { 'image_path': 'assets/images/icon-710x599.png' }; - expect(main_dart.hasPlatformConfig(flutterIconsConfig), false); + final config = FlutterLauncherIconsConfig.fromJson(flutterIconsConfig); + expect(config.hasPlatformConfig, false); }); test('No new Android icon needed - android: false', () { @@ -155,7 +157,8 @@ flutter_icons: 'android': false, 'ios': true }; - expect(main_dart.isNeedingNewAndroidIcon(flutterIconsConfig), false); + final config = FlutterLauncherIconsConfig.fromJson(flutterIconsConfig); + expect(config.isNeedingNewAndroidIcon, false); }); test('No new Android icon needed - no Android config', () { @@ -163,7 +166,8 @@ flutter_icons: 'image_path': 'assets/images/icon-710x599.png', 'ios': true }; - expect(main_dart.isNeedingNewAndroidIcon(flutterIconsConfig), false); + final config = FlutterLauncherIconsConfig.fromJson(flutterIconsConfig); + expect(config.isNeedingNewAndroidIcon, false); }); test('No new iOS icon needed - ios: false', () { @@ -172,7 +176,8 @@ flutter_icons: 'android': true, 'ios': false }; - expect(main_dart.isNeedingNewIOSIcon(flutterIconsConfig), false); + final config = FlutterLauncherIconsConfig.fromJson(flutterIconsConfig); + expect(config.isNeedingNewIOSIcon, false); }); test('No new iOS icon needed - no iOS config', () { @@ -180,6 +185,7 @@ flutter_icons: 'image_path': 'assets/images/icon-710x599.png', 'android': true }; - expect(main_dart.isNeedingNewIOSIcon(flutterIconsConfig), false); + final config = FlutterLauncherIconsConfig.fromJson(flutterIconsConfig); + expect(config.isNeedingNewIOSIcon, false); }); } diff --git a/test/windows/windows_icon_generator_test.mocks.dart b/test/windows/windows_icon_generator_test.mocks.dart index a53b647df8..e2889a865b 100644 --- a/test/windows/windows_icon_generator_test.mocks.dart +++ b/test/windows/windows_icon_generator_test.mocks.dart @@ -1,7 +1,8 @@ -// Mocks generated by Mockito 5.2.0 from annotations +// Mocks generated by Mockito 5.3.0 from annotations // in flutter_launcher_icons/test/windows/windows_icon_generator_test.dart. // Do not manually edit this file. +// ignore_for_file: no_leading_underscores_for_library_prefixes import 'package:cli_util/cli_logging.dart' as _i2; import 'package:flutter_launcher_icons/flutter_launcher_icons_config.dart' as _i3; @@ -17,10 +18,17 @@ import 'package:mockito/mockito.dart' as _i1; // ignore_for_file: prefer_const_constructors // ignore_for_file: unnecessary_parenthesis // ignore_for_file: camel_case_types +// ignore_for_file: subtype_of_sealed_class -class _FakeLogger_0 extends _i1.Fake implements _i2.Logger {} +class _FakeLogger_0 extends _i1.SmartFake implements _i2.Logger { + _FakeLogger_0(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); +} -class _FakeProgress_1 extends _i1.Fake implements _i2.Progress {} +class _FakeProgress_1 extends _i1.SmartFake implements _i2.Progress { + _FakeProgress_1(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); +} /// A class which mocks [FlutterLauncherIconsConfig]. /// @@ -40,6 +48,26 @@ class MockFlutterLauncherIconsConfig extends _i1.Mock .noSuchMethod(Invocation.getter(#removeAlphaIOS), returnValue: false) as bool); @override + bool get isNeedingNewIOSIcon => + (super.noSuchMethod(Invocation.getter(#isNeedingNewIOSIcon), + returnValue: false) as bool); + @override + bool get isNeedingNewAndroidIcon => + (super.noSuchMethod(Invocation.getter(#isNeedingNewAndroidIcon), + returnValue: false) as bool); + @override + bool get hasAndroidAdaptiveConfig => + (super.noSuchMethod(Invocation.getter(#hasAndroidAdaptiveConfig), + returnValue: false) as bool); + @override + bool get isCustomAndroidFile => + (super.noSuchMethod(Invocation.getter(#isCustomAndroidFile), + returnValue: false) as bool); + @override + bool get hasPlatformConfig => + (super.noSuchMethod(Invocation.getter(#hasPlatformConfig), + returnValue: false) as bool); + @override Map toJson() => (super.noSuchMethod(Invocation.method(#toJson, []), returnValue: {}) as Map); @@ -77,7 +105,8 @@ class MockFLILogger extends _i1.Mock implements _i4.FLILogger { as bool); @override _i2.Logger get rawLogger => (super.noSuchMethod(Invocation.getter(#rawLogger), - returnValue: _FakeLogger_0()) as _i2.Logger); + returnValue: _FakeLogger_0(this, Invocation.getter(#rawLogger))) + as _i2.Logger); @override void error(Object? message) => super.noSuchMethod(Invocation.method(#error, [message]), @@ -91,7 +120,9 @@ class MockFLILogger extends _i1.Mock implements _i4.FLILogger { super.noSuchMethod(Invocation.method(#info, [message]), returnValueForMissingStub: null); @override - _i2.Progress progress(String? message) => - (super.noSuchMethod(Invocation.method(#progress, [message]), - returnValue: _FakeProgress_1()) as _i2.Progress); + _i2.Progress progress(String? message) => (super.noSuchMethod( + Invocation.method(#progress, [message]), + returnValue: + _FakeProgress_1(this, Invocation.method(#progress, [message]))) + as _i2.Progress); } From e2a077ae271d199ad124780e1e260c973246cad8 Mon Sep 17 00:00:00 2001 From: p-mazhnik Date: Wed, 3 Aug 2022 20:35:44 +0300 Subject: [PATCH 3/3] test: use matchers instead of actual values --- test/android_test.dart | 6 ++-- test/flutter_launcher_icons_config_test.dart | 6 ++-- test/main_test.dart | 30 ++++++++++---------- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/test/android_test.dart b/test/android_test.dart index 685e55e22b..20425fac5e 100644 --- a/test/android_test.dart +++ b/test/android_test.dart @@ -35,7 +35,7 @@ void main() { expect( FlutterLauncherIconsConfig.fromJson(flutterIconsConfig) .isCustomAndroidFile, - false, + isFalse, ); final Map flutterIconsNewIconConfig = { @@ -46,7 +46,7 @@ void main() { expect( FlutterLauncherIconsConfig.fromJson(flutterIconsNewIconConfig) .isCustomAndroidFile, - true, + isTrue, ); }); @@ -60,7 +60,7 @@ void main() { expect( FlutterLauncherIconsConfig.fromJson(flutterIconsNewIconConfig) .getImagePathAndroid(), - 'assets/images/icon-android.png', + equals('assets/images/icon-android.png'), ); }); diff --git a/test/flutter_launcher_icons_config_test.dart b/test/flutter_launcher_icons_config_test.dart index 2d2c9df8ba..2b99f52f3b 100644 --- a/test/flutter_launcher_icons_config_test.dart +++ b/test/flutter_launcher_icons_config_test.dart @@ -81,18 +81,18 @@ void main() { final configs = FlutterLauncherIconsConfig.loadConfigFromPath(path, '.'); expect(configs, isNotNull); const String imagePath = 'assets/images/icon-710x599.png'; - expect(configs!.imagePath, imagePath); + expect(configs!.imagePath, equals(imagePath)); // android configs expect(configs.android, isTrue); expect(configs.imagePathAndroid, isNull); - expect(configs.getImagePathAndroid(), imagePath); + expect(configs.getImagePathAndroid(), equals(imagePath)); expect(configs.adaptiveIconBackground, isNull); expect(configs.adaptiveIconForeground, isNull); expect(configs.minSdkAndroid, equals(21)); // ios configs expect(configs.ios, isTrue); expect(configs.imagePathIOS, isNull); - expect(configs.getImagePathIOS(), imagePath); + expect(configs.getImagePathIOS(), equals(imagePath)); expect(configs.removeAlphaIOS, isFalse); // web configs expect(configs.webConfig, isNull); diff --git a/test/main_test.dart b/test/main_test.dart index 346a7cf3ff..41ac4dc358 100644 --- a/test/main_test.dart +++ b/test/main_test.dart @@ -6,7 +6,7 @@ import 'package:flutter_launcher_icons/flutter_launcher_icons_config.dart'; import 'package:flutter_launcher_icons/ios.dart' as ios; import 'package:flutter_launcher_icons/main.dart' show defaultConfigFile; import 'package:flutter_launcher_icons/main.dart' as main_dart; -import 'package:path/path.dart'; +import 'package:path/path.dart' show join; import 'package:test/test.dart'; // Unit tests for main.dart @@ -61,7 +61,7 @@ flutter_icons: final FlutterLauncherIconsConfig? config = main_dart.loadConfigFileFromArgResults(argResults); expect(config, isNotNull); - expect(config!.android, true); + expect(config!.android, isTrue); }); test('default_use_pubspec', () async { await setCurrentDirectory('pubspec_only'); @@ -74,7 +74,7 @@ flutter_icons: final FlutterLauncherIconsConfig? config = main_dart.loadConfigFileFromArgResults(argResults); expect(config, isNotNull); - expect(config!.ios, false); + expect(config!.ios, isFalse); // read pubspec if provided file is not found argResults = parser.parse(['-f', defaultConfigFile]); @@ -93,7 +93,7 @@ flutter_icons: final FlutterLauncherIconsConfig? config = main_dart.loadConfigFileFromArgResults(argResults); expect(config, isNotNull); - expect(config!.ios, true); + expect(config!.ios, isTrue); // should fail if no argument argResults = parser.parse([]); @@ -112,15 +112,15 @@ flutter_icons: 'ios': true }; final config = FlutterLauncherIconsConfig.fromJson(flutterIconsConfig); - expect(config.getImagePathAndroid(), 'assets/images/icon-710x599.png'); - expect(config.getImagePathIOS(), 'assets/images/icon-710x599.png'); + expect(config.getImagePathAndroid(), equals('assets/images/icon-710x599.png')); + expect(config.getImagePathIOS(), equals('assets/images/icon-710x599.png')); final Map flutterIconsConfigAndroid = { 'image_path_android': 'assets/images/icon-710x599.png', 'android': true, 'ios': true }; final configAndroid = FlutterLauncherIconsConfig.fromJson(flutterIconsConfigAndroid); - expect(configAndroid.getImagePathAndroid(), 'assets/images/icon-710x599.png'); + expect(configAndroid.getImagePathAndroid(), equals('assets/images/icon-710x599.png')); expect(configAndroid.getImagePathIOS(), isNull); final Map flutterIconsConfigBoth = { 'image_path_android': 'assets/images/icon-android.png', @@ -129,8 +129,8 @@ flutter_icons: 'ios': true }; final configBoth = FlutterLauncherIconsConfig.fromJson(flutterIconsConfigBoth); - expect(configBoth.getImagePathAndroid(), 'assets/images/icon-android.png'); - expect(configBoth.getImagePathIOS(), 'assets/images/icon-ios.png'); + expect(configBoth.getImagePathAndroid(), equals('assets/images/icon-android.png')); + expect(configBoth.getImagePathIOS(), equals('assets/images/icon-ios.png')); }); test('At least one platform is in config file', () { @@ -140,7 +140,7 @@ flutter_icons: 'ios': true }; final config = FlutterLauncherIconsConfig.fromJson(flutterIconsConfig); - expect(config.hasPlatformConfig, true); + expect(config.hasPlatformConfig, isTrue); }); test('No platform specified in config', () { @@ -148,7 +148,7 @@ flutter_icons: 'image_path': 'assets/images/icon-710x599.png' }; final config = FlutterLauncherIconsConfig.fromJson(flutterIconsConfig); - expect(config.hasPlatformConfig, false); + expect(config.hasPlatformConfig, isFalse); }); test('No new Android icon needed - android: false', () { @@ -158,7 +158,7 @@ flutter_icons: 'ios': true }; final config = FlutterLauncherIconsConfig.fromJson(flutterIconsConfig); - expect(config.isNeedingNewAndroidIcon, false); + expect(config.isNeedingNewAndroidIcon, isFalse); }); test('No new Android icon needed - no Android config', () { @@ -167,7 +167,7 @@ flutter_icons: 'ios': true }; final config = FlutterLauncherIconsConfig.fromJson(flutterIconsConfig); - expect(config.isNeedingNewAndroidIcon, false); + expect(config.isNeedingNewAndroidIcon, isFalse); }); test('No new iOS icon needed - ios: false', () { @@ -177,7 +177,7 @@ flutter_icons: 'ios': false }; final config = FlutterLauncherIconsConfig.fromJson(flutterIconsConfig); - expect(config.isNeedingNewIOSIcon, false); + expect(config.isNeedingNewIOSIcon, isFalse); }); test('No new iOS icon needed - no iOS config', () { @@ -186,6 +186,6 @@ flutter_icons: 'android': true }; final config = FlutterLauncherIconsConfig.fromJson(flutterIconsConfig); - expect(config.isNeedingNewIOSIcon, false); + expect(config.isNeedingNewIOSIcon, isFalse); }); }