Skip to content

Commit

Permalink
Add units tests
Browse files Browse the repository at this point in the history
refs #6
  • Loading branch information
brolandeau committed Jan 3, 2025
1 parent fabac98 commit 455f87e
Show file tree
Hide file tree
Showing 72 changed files with 1,177 additions and 74 deletions.
19 changes: 19 additions & 0 deletions .github/workflows/flutter_unit_tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# SPDX-FileCopyrightText: 2025 Benoit Rolandeau <[email protected]>
#
# SPDX-License-Identifier: MIT

name: Flutter Unit Tests
on: [pull_request]

jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
with:
submodules: recursive
- name: Set up Flutter
uses: subosito/flutter-action@v1
- run: for i in $(git ls-files --recurse-submodules "*/pubspec.yaml"); do
(cd "${i%pubspec.yaml}" && flutter test -r github --flavor test); done
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ SPDX-FileCopyrightText: 2024 Benoit Rolandeau <[email protected]>
SPDX-License-Identifier: MIT
-->

<a href="https://github.com/borlnov/flutterbrolibs/actions">

Check failure on line 7 in README.md

View workflow job for this annotation

GitHub Actions / lint

Inline HTML

README.md:7:1 MD033/no-inline-html Inline HTML [Element: a] https://github.com/DavidAnson/markdownlint/blob/v0.36.1/doc/md033.md

Check failure on line 7 in README.md

View workflow job for this annotation

GitHub Actions / lint

First line in a file should be a top-level heading

README.md:7 MD041/first-line-heading/first-line-h1 First line in a file should be a top-level heading [Context: "<a href="https://github.com/bo..."] https://github.com/DavidAnson/markdownlint/blob/v0.36.1/doc/md041.md

Check failure on line 7 in README.md

View workflow job for this annotation

GitHub Actions / lint

Inline HTML

README.md:7:1 MD033/no-inline-html Inline HTML [Element: a] https://github.com/DavidAnson/markdownlint/blob/v0.36.1/doc/md033.md

Check failure on line 7 in README.md

View workflow job for this annotation

GitHub Actions / lint

First line in a file should be a top-level heading

README.md:7 MD041/first-line-heading/first-line-h1 First line in a file should be a top-level heading [Context: "<a href="https://github.com/bo..."] https://github.com/DavidAnson/markdownlint/blob/v0.36.1/doc/md041.md
<img src="https://github.com/borlnov/flutterbrolibs/workflows/flutter_unit_tests/badge.svg" alt=”Build Status”>

Check failure on line 8 in README.md

View workflow job for this annotation

GitHub Actions / lint

Line length

README.md:8:101 MD013/line-length Line length [Expected: 100; Actual: 111] https://github.com/DavidAnson/markdownlint/blob/v0.36.1/doc/md013.md

Check failure on line 8 in README.md

View workflow job for this annotation

GitHub Actions / lint

Line length

README.md:8:101 MD013/line-length Line length [Expected: 100; Actual: 111] https://github.com/DavidAnson/markdownlint/blob/v0.36.1/doc/md013.md
</a>

# Flutter Bro libraries <!-- omit from toc -->

## Table of contents
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@
// SPDX-License-Identifier: MIT

import 'package:bro_abstract_logger/bro_abstract_logger.dart';
import 'package:bro_abstract_manager/bro_abstract_manager.dart';

/// This class is used to build a [VoidLoggerManager].
class VoidLoggerBuilder extends AbsManagerBuilder<VoidLoggerManager> {
class VoidLoggerBuilder extends AbsLoggerBuilder<VoidLoggerManager> {
/// Class constructor.
const VoidLoggerBuilder() : super(VoidLoggerManager.new);

Expand Down
6 changes: 3 additions & 3 deletions bro_abstract_logger/test/abstract_logger_manager_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
import 'package:bro_abstract_logger/bro_abstract_logger.dart';
import 'package:flutter_test/flutter_test.dart';

import 'struct/helpers/test_print_logger.dart';
import 'struct/models/test_log_model.dart';
import 'struct/services/a_logger_manager.dart';
import 'mock/helpers/test_print_logger.dart';
import 'mock/models/test_log_model.dart';
import 'mock/services/a_logger_manager.dart';

/// Test the [AbstractLoggerManager] behaviours.
void main() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
import 'package:bro_abstract_logger/bro_abstract_logger.dart';
import 'package:flutter_test/flutter_test.dart';

import 'struct/helpers/test_print_logger.dart';
import 'struct/models/test_log_model.dart';
import 'struct/services/a_logger_manager.dart';
import 'struct/services/b_multi_logger_manager.dart';
import 'mock/helpers/test_print_logger.dart';
import 'mock/models/test_log_model.dart';
import 'mock/services/a_logger_manager.dart';
import 'mock/services/b_multi_logger_manager.dart';

/// Test the [AbstractMultiLoggerManager] behaviours.
void main() {
Expand Down
4 changes: 2 additions & 2 deletions bro_abstract_logger/test/logger_helper_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
import 'package:bro_abstract_logger/bro_abstract_logger.dart';
import 'package:flutter_test/flutter_test.dart';

import 'struct/helpers/test_print_logger.dart';
import 'struct/models/test_log_model.dart';
import 'mock/helpers/test_print_logger.dart';
import 'mock/models/test_log_model.dart';

/// Test the logger helper behaviours.
void main() {
Expand Down
4 changes: 2 additions & 2 deletions bro_abstract_manager/test/abs_manager_builder_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@

import 'package:flutter_test/flutter_test.dart';

import 'struct/services/a_manager_builder.dart';
import 'struct/types/manager_status.dart';
import 'mock/services/a_manager_builder.dart';
import 'mock/types/manager_status.dart';

/// Test the abstract manager builder.
void main() {
Expand Down
6 changes: 3 additions & 3 deletions bro_config_manager/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ syntax:
```yaml
key:
__name: ENV_VAR_NAME
__type: int
__format: int
```

Here is an example of a mapping file:
Expand All @@ -135,7 +135,7 @@ logger:
# If true, this will enable the console logger
enabled:
__name: LOGGER_CONSOLE_ENABLED
__type: bool
__format: bool

# This contains the settings for the file logger
file:
Expand All @@ -146,7 +146,7 @@ logger:
# If true, this will enable the file logger
enabled:
__name: LOGGER_FILE_ENABLED
__type: bool
__format: bool
```
The supported types are:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
//
// SPDX-License-Identifier: MIT

import 'package:bro_abstract_logger/bro_abstract_logger.dart';
import 'package:bro_config_manager/src/types/config_environment_type.dart';
import 'package:equatable/equatable.dart';

Expand Down
2 changes: 2 additions & 0 deletions bro_config_manager/lib/src/services/abs_config_manager.dart
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,9 @@ abstract class AbstractConfigManager extends AbsWithLifeCycle with MixinManagerW
);
}

/// {@template bro_config_manager.AbstractConfigManager.getInitConfigManagerModel}
/// This method returns the model to initialize the ConfigManager.
/// {@endtemplate}
@protected
Future<InitConfigManagerModel> getInitConfigManagerModel();
}
5 changes: 5 additions & 0 deletions bro_config_manager/lib/src/services/config_companion.dart
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ class ConfigCompanion {
);
}

/// Reset the singleton instance of the class.
static void resetSingleton() {
_instance = null;
}

/// This is the config [_json]
final Map<String, dynamic> _json;

Expand Down
31 changes: 14 additions & 17 deletions bro_config_manager/lib/src/utilities/global_parse_file_utility.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@
//
// SPDX-License-Identifier: MIT

import 'dart:io';

import 'package:bro_abstract_logger/bro_abstract_logger.dart';
import 'package:bro_config_manager/src/data/config_files_constants.dart' as config_files_constants;
import 'package:bro_file_utility/bro_file_utility.dart';
import 'package:bro_yaml_utility/bro_yaml_utility.dart';

/// Utility class to parse a YAML file content
Expand All @@ -17,12 +16,12 @@ abstract final class GlobalParseFileUtility {
/// [fileName] is the name of the file to parse (it contains the file extension).
///
/// If not null, the [logger] will be used to log the errors.
static ({bool success, Map<String, dynamic>? value}) parseConfigFile({
static Future<({bool success, Map<String, dynamic>? value})> parseConfigFile({
required String configFolderPath,
required String fileName,
LoggerHelper? logger,
}) {
final result = _readFileContent(
}) async {
final result = await _readAssetFileContent(
configFolderPath: configFolderPath,
fileName: fileName,
logger: logger,
Expand Down Expand Up @@ -57,25 +56,23 @@ abstract final class GlobalParseFileUtility {
/// [fileName] is the name of the file to parse (it contains the file extension).
///
/// If not null, the [logger] will be used to log the errors.
static ({bool success, String? content}) _readFileContent({
static Future<({bool success, String? content})> _readAssetFileContent({
required String configFolderPath,
required String fileName,
required LoggerHelper? logger,
}) {
}) async {
for (final extension in config_files_constants.configYamlExtensions) {
final file = File('$configFolderPath/$fileName$extension');
if (!file.existsSync()) {
continue;
}
final content = await AssetsUtility.loadAssetString(
assetPath: '$configFolderPath/$fileName$extension',
logger: logger,
);

String? content;
try {
content = file.readAsStringSync();
} catch (e) {
logger?.error("Failed to read the content of the file: $fileName$extension, error: $e");
if (content == null) {
// The file may not exist, we continue to the next extension
continue;
}

return (success: (content != null), content: content);
return (success: true, content: content);
}

return (success: true, content: null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import 'package:bro_config_manager/src/data/config_files_constants.dart' as conf
import 'package:bro_config_manager/src/types/config_environment_type.dart';
import 'package:bro_config_manager/src/utilities/parse_config_file_utility.dart';
import 'package:bro_config_manager/src/utilities/parse_env_utility.dart';
import 'package:bro_yaml_utility/bro_yaml_utility.dart';

/// Utility class to parse all the config files, dot files and environment values and merge them
/// together.
Expand Down Expand Up @@ -39,7 +38,7 @@ abstract final class ParseAllConfigsUtility {
required Map<String, String> constEnvsValues,
LoggerHelper? logger,
}) async {
final configValues = ParseConfigFileUtility.parseConfigFiles(
final configValues = await ParseConfigFileUtility.parseConfigFiles(
configFolderPath: configFolderPath,
environmentType: environmentType,
logger: logger,
Expand All @@ -49,18 +48,15 @@ abstract final class ParseAllConfigsUtility {
return null;
}

final envConfigValues = await ParseEnvUtility.parseEnvConfig(
final mergedConfigValues = await ParseEnvUtility.mergeWithEnvConfig(
configFolderPath: configFolderPath,
environmentType: environmentType,
constEnvsValues: constEnvsValues,
configValues: configValues,
logger: logger,
);

if (envConfigValues == null) {
return null;
}

return JsonUtility.mergeJson(configValues, envConfigValues);
return mergedConfigValues;
}

/// Guess the environment type from the environment variables passed when building the app.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,24 +24,24 @@ abstract final class ParseConfigFileUtility {
/// - default.yaml
/// - [environmentType].yaml
/// - local.yaml
static Map<String, dynamic>? parseConfigFiles({
static Future<Map<String, dynamic>?> parseConfigFiles({
required String configFolderPath,
required ConfigEnvironmentType environmentType,
LoggerHelper? logger,
}) {
final defaultConfig = GlobalParseFileUtility.parseConfigFile(
}) async {
final defaultConfig = await GlobalParseFileUtility.parseConfigFile(
configFolderPath: configFolderPath,
fileName: config_files_constants.defaultConfigFileName,
logger: logger,
);

final envConfig = GlobalParseFileUtility.parseConfigFile(
final envConfig = await GlobalParseFileUtility.parseConfigFile(
configFolderPath: configFolderPath,
fileName: environmentType.fileBaseName,
logger: logger,
);

final localConfig = GlobalParseFileUtility.parseConfigFile(
final localConfig = await GlobalParseFileUtility.parseConfigFile(
configFolderPath: configFolderPath,
fileName: config_files_constants.localConfigFileName,
logger: logger,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,17 @@ import 'package:bro_config_manager/src/utilities/global_parse_file_utility.dart'

/// Utility class to parse the env mapping file.
abstract final class ParseEnvMappingFileUtility {
/// Transform the [envValues] to a JSON object which can be used as config file.
/// Merge the environment mapping values with the config values.
///
/// If not null, the [logger] will be used to log the errors.
///
/// Returns the JSON object or null if an error occurred.
static Map<String, dynamic>? transformEnvMapValuesToJson({
static Map<String, dynamic>? mergeWithEnvMapValues({
required List<EnvMapValueElement> envValues,
required Map<String, dynamic> configValues,
LoggerHelper? logger,
}) {
final json = <String, dynamic>{};
final json = Map<String, dynamic>.from(configValues);
var tmpJson = json;
for (final envValue in envValues) {
final jsonPath = envValue.jsonPath;
Expand All @@ -28,15 +29,18 @@ abstract final class ParseEnvMappingFileUtility {
if (idx == jsonPath.length - 1) {
tmpJson[key] = envValue.value;
} else {
final tmpValue = tmpJson[key] ?? <String, dynamic>{};
var tmpValue = tmpJson[key];

if (tmpValue is! Map<String, dynamic>) {
if (tmpValue == null) {
tmpJson[key] = <String, dynamic>{};
tmpValue = tmpJson[key];
} else if (tmpValue is! Map<String, dynamic>) {
logger?.warn("Env map parsing: failed to parse the element: $envValue, the json path "
"is not valid, the key: $key is used for a value and a map");
return null;
}

tmpJson = tmpValue;
tmpJson = tmpValue as Map<String, dynamic>;
}
}

Expand All @@ -53,11 +57,11 @@ abstract final class ParseEnvMappingFileUtility {
/// If not null, the [logger] will be used to log the errors.
///
/// Returns the parsed elements or null if an error occurred.
static List<EnvMapFileElement>? parseMappingFile({
static Future<List<EnvMapFileElement>?> parseMappingFile({
required String configFolderPath,
LoggerHelper? logger,
}) {
final envMapFile = GlobalParseFileUtility.parseConfigFile(
}) async {
final envMapFile = await GlobalParseFileUtility.parseConfigFile(
configFolderPath: configFolderPath,
fileName: config_files_constants.envMapFileName,
logger: logger,
Expand Down Expand Up @@ -121,7 +125,7 @@ abstract final class ParseEnvMappingFileUtility {
if (value is String) {
final parsedElement = EnvMapFileElement.fromStringType(
envKey: value,
currentJsonPath: currentJsonPath,
currentJsonPath: newJsonPath,
);

if (parsedElement == null) {
Expand Down
11 changes: 7 additions & 4 deletions bro_config_manager/lib/src/utilities/parse_env_utility.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ import 'package:bro_config_manager/src/utilities/parse_env_mapping_file_utility.

/// The utility class to parse the environment configuration.
abstract final class ParseEnvUtility {
/// Parse the environment configuration: the dot env files and the environment mapping file.
/// Parse the environment configuration: the dot env files and the environment mapping file and
/// merge them with the config values ([configValues])
///
/// [configFolderPath] is the path to the folder containing the config files.
///
Expand All @@ -24,13 +25,14 @@ abstract final class ParseEnvUtility {
/// If not null, the [logger] will be used to log the errors.
///
/// Returns the parsed environment configuration or null if an error occurred.
static Future<Map<String, dynamic>?> parseEnvConfig({
static Future<Map<String, dynamic>?> mergeWithEnvConfig({
required String configFolderPath,
required ConfigEnvironmentType environmentType,
required Map<String, String> constEnvsValues,
required Map<String, dynamic> configValues,
LoggerHelper? logger,
}) async {
final envMapFileElements = ParseEnvMappingFileUtility.parseMappingFile(
final envMapFileElements = await ParseEnvMappingFileUtility.parseMappingFile(
configFolderPath: configFolderPath,
logger: logger,
);
Expand All @@ -51,8 +53,9 @@ abstract final class ParseEnvUtility {
return null;
}

return ParseEnvMappingFileUtility.transformEnvMapValuesToJson(
return ParseEnvMappingFileUtility.mergeWithEnvMapValues(
envValues: envMapValues,
configValues: configValues,
logger: logger,
);
}
Expand Down
Loading

0 comments on commit 455f87e

Please sign in to comment.