fix(shorebird_cli): verify that validators can be run before running them (#1254)

This commit is contained in:
Bryan Oltman
2023-09-11 16:22:44 -04:00
committed by GitHub
parent d12faa7e58
commit ba1c06dbff
7 changed files with 69 additions and 7 deletions
@@ -26,6 +26,13 @@ class ValidationFailedException implements PreconditionFailedException {
ExitCode get exitCode => ExitCode.config;
}
class UnsupportedContextException implements PreconditionFailedException {
// coverage:ignore-start
@override
ExitCode get exitCode => ExitCode.unavailable;
// coverage:ignore-end
}
class UnsupportedOperatingSystemException
implements PreconditionFailedException {
@override
@@ -80,6 +87,13 @@ class ShorebirdValidator {
throw ShorebirdNotInitializedException();
}
for (final validator in validators) {
if (!validator.canRunInCurrentContext()) {
logger.err(validator.incorrectContextMessage);
throw UnsupportedContextException();
}
}
final validationIssues = await runValidators(validators);
if (validationIssuesContainsError(validationIssues)) {
logValidationFailure(issues: validationIssues);
@@ -24,6 +24,14 @@ class AndroidInternetPermissionValidator extends Validator {
@override
bool canRunInCurrentContext() => _androidSrcDirectory.existsSync();
// coverage:ignore-start
@override
String get incorrectContextMessage => '''
The ${_androidSrcDirectory.path} directory does not exist.
The command you are running must be run at the root of a Flutter app project that supports the Android platform. If you are releasing a Flutter module, use 'aar' in place of 'android' in your shorebird command.''';
// coverage:ignore-end
@override
Future<List<ValidationIssue>> validate() async {
const manifestFileName = 'AndroidManifest.xml';
@@ -21,9 +21,6 @@ class ShorebirdFlutterValidator extends Validator {
@override
String get description => 'Flutter install is correct';
@override
bool canRunInCurrentContext() => true;
@override
Future<List<ValidationIssue>> validate() async {
final issues = <ValidationIssue>[];
@@ -10,9 +10,6 @@ class ShorebirdVersionValidator extends Validator {
@override
String get description => 'Shorebird is up-to-date';
@override
bool canRunInCurrentContext() => true;
@override
Future<List<ValidationIssue>> validate() async {
final bool isShorebirdUpToDate;
@@ -85,5 +85,10 @@ abstract class Validator {
/// Not all validators use [process].
Future<List<ValidationIssue>> validate();
bool canRunInCurrentContext();
/// Whether it makes sense to run the validator in the current working
/// directory.
bool canRunInCurrentContext() => true;
/// User-facing message explaining why [canRunInCurrentContext] is false.
String? get incorrectContextMessage => null;
}
@@ -153,6 +153,23 @@ void main() {
),
).called(1);
});
test(
'''throws UnsupportedContextException if validator cannot be run in current context''',
() async {
const errorMessage = 'Cannot run in this context';
when(() => validator.canRunInCurrentContext()).thenReturn(false);
when(() => validator.incorrectContextMessage).thenReturn(errorMessage);
await expectLater(
runWithOverrides(
() => shorebirdValidator.validatePreconditions(
validators: [validator],
),
),
throwsA(isA<UnsupportedContextException>()),
);
verify(() => logger.err(errorMessage)).called(1);
});
});
});
}
@@ -0,0 +1,24 @@
import 'package:shorebird_cli/src/validators/validators.dart';
import 'package:test/test.dart';
void main() {
group(Validator, () {
test('canRunInContext is true by default', () {
expect(FakeValidator().canRunInCurrentContext(), equals(true));
});
test('incorrectContextMessage is null by default', () {
expect(FakeValidator().incorrectContextMessage, isNull);
});
});
}
class FakeValidator extends Validator {
@override
String get description => 'A fake validator for testing';
@override
Future<List<ValidationIssue>> validate() async {
return [];
}
}