@@ -7,6 +7,7 @@ import 'package:mason/mason.dart';
77import 'package:meta/meta.dart' ;
88import 'package:path/path.dart' as path;
99import 'package:very_good_cli/src/cli/cli.dart' ;
10+ import 'package:very_good_cli/src/very_good_config/very_good_config.dart' ;
1011
1112/// Options for configuring the Dart test command.
1213class DartTestOptions {
@@ -32,18 +33,53 @@ class DartTestOptions {
3233 });
3334
3435 /// Parses [ArgResults] into a [DartTestOptions] instance.
35- factory DartTestOptions .parse (ArgResults argResults) {
36- final concurrency = argResults['concurrency' ] as String ;
37- final collectCoverage = argResults['coverage' ] as bool ;
38- final minCoverage = double .tryParse (
39- argResults['min-coverage' ] as String ? ?? '' ,
36+ ///
37+ /// When [config] is provided, its values are used as defaults for any
38+ /// option that was not explicitly parsed on the command line.
39+ factory DartTestOptions .parse (
40+ ArgResults argResults, {
41+ VeryGoodConfig config = VeryGoodConfig .empty,
42+ }) {
43+ final testConfig = config.dart.test;
44+
45+ final concurrency = _resolveArg (
46+ argResults,
47+ 'concurrency' ,
48+ testConfig.concurrency,
49+ );
50+ final collectCoverage = _resolveArg (
51+ argResults,
52+ 'coverage' ,
53+ testConfig.coverage,
54+ );
55+ final minCoverageString = _resolveArg <String ?>(
56+ argResults,
57+ 'min-coverage' ,
58+ testConfig.minCoverage,
59+ );
60+ final minCoverage = double .tryParse (minCoverageString ?? '' );
61+ final showUncovered = _resolveArg (
62+ argResults,
63+ 'show-uncovered' ,
64+ testConfig.showUncovered,
65+ );
66+ final excludeTags = _resolveArg <String ?>(
67+ argResults,
68+ 'exclude-tags' ,
69+ testConfig.excludeTags,
70+ );
71+ final tags = _resolveArg <String ?>(argResults, 'tags' , testConfig.tags);
72+ final excludeFromCoverage = _resolveArg <String ?>(
73+ argResults,
74+ 'exclude-coverage' ,
75+ testConfig.excludeCoverage,
76+ );
77+ final collectCoverageFromString = _resolveArg <String >(
78+ argResults,
79+ 'collect-coverage-from' ,
80+ testConfig.collectCoverageFrom,
81+ fallbackValue: 'imports' ,
4082 );
41- final showUncovered = argResults['show-uncovered' ] as bool ;
42- final excludeTags = argResults['exclude-tags' ] as String ? ;
43- final tags = argResults['tags' ] as String ? ;
44- final excludeFromCoverage = argResults['exclude-coverage' ] as String ? ;
45- final collectCoverageFromString =
46- argResults['collect-coverage-from' ] as String ? ?? 'imports' ;
4783 final collectCoverageFrom = CoverageCollectionMode .fromString (
4884 collectCoverageFromString,
4985 );
@@ -52,17 +88,46 @@ class DartTestOptions {
5288 final randomSeed = randomOrderingSeed == 'random'
5389 ? Random ().nextInt (4294967295 ).toString ()
5490 : randomOrderingSeed;
55- final optimizePerformance = argResults['optimization' ] as bool ;
56- final failFast = argResults['fail-fast' ] as bool ;
91+ final optimizePerformance = _resolveArg (
92+ argResults,
93+ 'optimization' ,
94+ testConfig.optimization,
95+ );
96+ final failFast = _resolveArg (
97+ argResults,
98+ 'fail-fast' ,
99+ testConfig.failFast,
100+ );
57101 final forceAnsi = argResults['force-ansi' ] as bool ? ;
58- final platform = argResults['platform' ] as String ? ;
59- final reportOn = (argResults['report-on' ] as List <String >)
102+ final platform = _resolveArg <String ?>(
103+ argResults,
104+ 'platform' ,
105+ testConfig.platform,
106+ );
107+ final reportOn = _resolveArg <List <String >>(
108+ argResults,
109+ 'report-on' ,
110+ testConfig.reportOn,
111+ );
112+ final effectiveReportOn = reportOn
60113 .expand ((e) => e.split (RegExp (r'[,\s]+' )))
61114 .where ((e) => e.isNotEmpty)
62115 .toList ();
63- final runSkipped = argResults['run-skipped' ] as bool ;
64- final checkIgnore = argResults['check-ignore' ] as bool ;
65- final fileReporter = argResults['file-reporter' ] as String ? ;
116+ final runSkipped = _resolveArg (
117+ argResults,
118+ 'run-skipped' ,
119+ testConfig.runSkipped,
120+ );
121+ final checkIgnore = _resolveArg (
122+ argResults,
123+ 'check-ignore' ,
124+ testConfig.checkIgnore,
125+ );
126+ final fileReporter = _resolveArg <String ?>(
127+ argResults,
128+ 'file-reporter' ,
129+ testConfig.fileReporter,
130+ );
66131 final rest = argResults.rest;
67132
68133 return DartTestOptions ._(
@@ -79,7 +144,7 @@ class DartTestOptions {
79144 failFast: failFast,
80145 forceAnsi: forceAnsi,
81146 platform: platform,
82- reportOn: reportOn ,
147+ reportOn: effectiveReportOn ,
83148 runSkipped: runSkipped,
84149 checkIgnore: checkIgnore,
85150 fileReporter: fileReporter,
@@ -144,6 +209,27 @@ class DartTestOptions {
144209 final List <String > rest;
145210}
146211
212+ /// Resolves the value for the argument named [name] against a `very_good.yaml`
213+ /// configuration value.
214+ ///
215+ /// Resolution follows a fixed precedence, from highest to lowest:
216+ ///
217+ /// 1. A command line argument that was explicitly parsed.
218+ /// 2. [configValue] , the corresponding value from the configuration file.
219+ /// 3. [fallbackValue] , used when neither the command line nor the configuration
220+ /// provide a value (typically the argument's command line default).
221+ T _resolveArg <T >(
222+ ArgResults argResults,
223+ String name,
224+ T ? configValue, {
225+ T ? fallbackValue,
226+ }) {
227+ final value = configValue != null && ! argResults.wasParsed (name)
228+ ? configValue
229+ : argResults[name] as T ? ;
230+ return (value ?? fallbackValue) as T ;
231+ }
232+
147233/// Signature for the [Dart.installed] method.
148234typedef DartInstalledCommand = Future <bool > Function ({required Logger logger});
149235
@@ -327,9 +413,20 @@ This command should be run from the root of your Dart project.''');
327413 return ExitCode .noInput.code;
328414 }
329415
416+ final VeryGoodConfig config;
417+ try {
418+ config = VeryGoodConfig .loadFromClosestAncestor (Directory (targetPath));
419+ } on VeryGoodConfigParseException catch (e) {
420+ _logger.err (
421+ 'Could not read `$veryGoodConfigFileName `.\n '
422+ '${e .message }' ,
423+ );
424+ return ExitCode .config.code;
425+ }
426+
330427 final isDartInstalled = await _dartInstalled (logger: _logger);
331428
332- final options = DartTestOptions .parse (_argResults);
429+ final options = DartTestOptions .parse (_argResults, config : config );
333430
334431 if (isDartInstalled) {
335432 try {
0 commit comments