runGen function
Writes (or checks) the generated test. Returns a human summary line, or throws StateError in check mode when stale.
Implementation
Future<String> runGen(
String projectRoot, {
required bool check,
required bool shots,
}) async {
final packageName = packageNameOf(projectRoot);
if (packageName == null) {
throw StateError('no pubspec.yaml at $projectRoot');
}
final entries = await discoverEntries(projectRoot);
final raw = generateTestFile(
packageName: packageName,
entries: entries,
shell: hasShellFor(projectRoot),
shots: shots,
);
// Emit format-clean code so consumers' `dart format` checks never fight
// the generated file.
final src = DartFormatter(
languageVersion: DartFormatter.latestLanguageVersion,
).format(raw);
final file = File(p.join(projectRoot, testRelPath));
final current = file.existsSync() ? file.readAsStringSync() : null;
if (check) {
if (current != src) {
throw StateError(
'$testRelPath is ${current == null ? 'missing' : 'STALE'} — '
'run `dart run greenroom` and commit the result.',
);
}
} else if (current != src) {
file
..parent.createSync(recursive: true)
..writeAsStringSync(src);
}
// The generated file imports flutter_test; without that dev_dependency
// `flutter test` cannot run it at all. Checked, not assumed.
final pubspec = File(p.join(projectRoot, 'pubspec.yaml')).readAsStringSync();
final missingTestDep = !RegExp(
r'^\s*flutter_test\s*:',
multiLine: true,
).hasMatch(pubspec);
final mountable = entries.where((e) => e.kind != 'missing').length;
final missing = entries.length - mountable;
final notes = entries.where((e) => e.note != null).map((e) => e.note!);
return [
if (missingTestDep)
'WARNING: pubspec.yaml has no flutter_test dependency — '
'`flutter test` cannot run the generated file. Add:\n'
' dev_dependencies:\n flutter_test:\n sdk: flutter',
'$testRelPath: $mountable mount tests'
'${missing > 0 ? ', $missing missing-entry obligations' : ''}'
'${shots ? ', screenshots on' : ''}'
'${check ? ' (check: fresh)' : ''}',
for (final n in notes) 'note — $n',
].join('\n');
}