runMatrix function
Generates every app of the matrixOf of modules with roleOptions in
directory, with the options of CI, analyzes each with
flutter analyze, and, in an app that some of the appTests apply to,
adds them and runs every test of the app with flutter test. Returns
the exit code: 0 if every app was generated with every module and every
step that the options of CI do not leave for later, has no issue and
passes its tests, and each of the appTests applies to some app; 1
otherwise.
With only, it checks only the apps of the matrix with those names,
such as every module (bloc), and runs the appTests that apply to
them; a name that no app of the matrix has is a problem too.
log gets what happens, by default the standard output; the apps stay
in directory, with the tests. commands run for each app.
Implementation
Future<int> runMatrix(
List<SmfModule> modules, {
required String directory,
Map<String, String?> roleOptions = const {},
List<MatrixAppTest> appTests = const [],
Set<String>? only,
void Function(String line)? log,
MatrixCommands commands = const MatrixCommands(),
}) async {
final run = _MatrixRun(
directory: directory,
appTests: appTests,
// coverage:ignore-start
// The defaults print to the terminal, create the apps with smf and
// analyze them with Flutter, as the runs of the matrix in CI do; the
// tests give their own.
say: log ?? (String line) => stdout.writeln(line),
create: commands.create ??
(arguments, onCreated) => runCli(
arguments,
modules: modules,
banner: false,
onCreated: onCreated,
),
analyze:
commands.analyze ?? (directory) => _flutter(['analyze'], directory),
// coverage:ignore-end
test: commands.test ?? runAppTests,
);
final (:apps, :failed) = await matrixOf(modules, roleOptions: roleOptions);
final problems = [
for (final result in failed)
'${result.contractCase}: ${result.errors.join('; ')}',
for (final name in only ?? const <String>{})
if (!apps.any((app) => app.name == name))
'No app of the matrix is $name.',
];
final checked = <MatrixApp>[];
for (final (index, app) in apps.indexed) {
if (only != null && !only.contains(app.name)) continue;
checked.add(app);
// An app keeps its number in the matrix when only some are checked.
problems.addAll(await run.check(app, 'app_${index + 1}'));
}
// Tests that apply to no app would leave CI without saying so. Those of
// the apps that are not checked run where the whole matrix is.
for (final test in appTests) {
if (!apps.any(test.appliesTo)) {
problems.add('The tests of ${test.directory} apply to no app.');
}
}
run.say('\n${checked.length} apps generated in $directory.');
if (problems.isEmpty) return 0;
run.say('Problems:');
problems.forEach(run.say);
return 1;
}