refactor(shorebird_cli): use scoped ShorebirdValidator (#996)
This commit is contained in:
@@ -16,6 +16,7 @@ import 'package:shorebird_cli/src/java.dart';
|
||||
import 'package:shorebird_cli/src/logger.dart';
|
||||
import 'package:shorebird_cli/src/platform.dart';
|
||||
import 'package:shorebird_cli/src/process.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validator.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_version_manager.dart';
|
||||
import 'package:shorebird_cli/src/xcodebuild.dart';
|
||||
|
||||
@@ -39,6 +40,7 @@ Future<void> main(List<String> args) async {
|
||||
loggerRef,
|
||||
platformRef,
|
||||
processRef,
|
||||
shorebirdValidatorRef,
|
||||
shorebirdVersionManagerRef,
|
||||
xcodeBuildRef,
|
||||
},
|
||||
|
||||
@@ -5,13 +5,11 @@ import 'package:mason_logger/mason_logger.dart';
|
||||
import 'package:shorebird_cli/src/auth/auth.dart';
|
||||
import 'package:shorebird_cli/src/command.dart';
|
||||
import 'package:shorebird_cli/src/logger.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_config_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_environment.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validation_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validator.dart';
|
||||
import 'package:shorebird_code_push_client/shorebird_code_push_client.dart';
|
||||
|
||||
class DowngradeAccountCommand extends ShorebirdCommand
|
||||
with ShorebirdConfigMixin, ShorebirdValidationMixin {
|
||||
class DowngradeAccountCommand extends ShorebirdCommand {
|
||||
DowngradeAccountCommand({super.buildCodePushClient});
|
||||
|
||||
@override
|
||||
@@ -23,7 +21,9 @@ class DowngradeAccountCommand extends ShorebirdCommand
|
||||
@override
|
||||
Future<int> run() async {
|
||||
try {
|
||||
await validatePreconditions(checkUserIsAuthenticated: true);
|
||||
await shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: true,
|
||||
);
|
||||
} on PreconditionFailedException catch (e) {
|
||||
return e.exitCode.code;
|
||||
}
|
||||
|
||||
@@ -4,16 +4,14 @@ import 'package:mason_logger/mason_logger.dart';
|
||||
import 'package:shorebird_cli/src/auth/auth.dart';
|
||||
import 'package:shorebird_cli/src/command.dart';
|
||||
import 'package:shorebird_cli/src/logger.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_config_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_environment.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validation_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validator.dart';
|
||||
import 'package:shorebird_code_push_client/shorebird_code_push_client.dart';
|
||||
|
||||
/// {@template upgrade_account_command}
|
||||
/// `shorebird account upgrade`
|
||||
/// {@endtemplate}
|
||||
class UpgradeAccountCommand extends ShorebirdCommand
|
||||
with ShorebirdConfigMixin, ShorebirdValidationMixin {
|
||||
class UpgradeAccountCommand extends ShorebirdCommand {
|
||||
/// {@macro upgrade_account_command}
|
||||
UpgradeAccountCommand({super.buildCodePushClient});
|
||||
|
||||
@@ -33,7 +31,7 @@ Please use $consoleLink instead.''',
|
||||
);
|
||||
|
||||
try {
|
||||
await validatePreconditions(
|
||||
await shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: true,
|
||||
);
|
||||
} on PreconditionFailedException catch (e) {
|
||||
|
||||
@@ -5,7 +5,7 @@ import 'package:shorebird_cli/src/command.dart';
|
||||
import 'package:shorebird_cli/src/logger.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_config_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_create_app_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validation_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validator.dart';
|
||||
import 'package:shorebird_code_push_client/shorebird_code_push_client.dart';
|
||||
|
||||
/// {@template create_app_command}
|
||||
@@ -14,10 +14,7 @@ import 'package:shorebird_code_push_client/shorebird_code_push_client.dart';
|
||||
/// Create a new app on Shorebird.
|
||||
/// {@endtemplate}
|
||||
class CreateAppCommand extends ShorebirdCommand
|
||||
with
|
||||
ShorebirdConfigMixin,
|
||||
ShorebirdValidationMixin,
|
||||
ShorebirdCreateAppMixin {
|
||||
with ShorebirdConfigMixin, ShorebirdCreateAppMixin {
|
||||
/// {@macro create_app_command}
|
||||
CreateAppCommand({super.buildCodePushClient}) {
|
||||
argParser.addOption(
|
||||
@@ -37,7 +34,7 @@ Defaults to the name in "pubspec.yaml".''',
|
||||
@override
|
||||
Future<int>? run() async {
|
||||
try {
|
||||
await validatePreconditions(
|
||||
await shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: true,
|
||||
);
|
||||
} on PreconditionFailedException catch (e) {
|
||||
|
||||
@@ -4,17 +4,15 @@ import 'package:mason_logger/mason_logger.dart';
|
||||
import 'package:shorebird_cli/src/auth/auth.dart';
|
||||
import 'package:shorebird_cli/src/command.dart';
|
||||
import 'package:shorebird_cli/src/logger.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_config_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_environment.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validation_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validator.dart';
|
||||
|
||||
/// {@template delete_app_command}
|
||||
///
|
||||
/// `shorebird apps delete`
|
||||
/// Delete an existing app on Shorebird.
|
||||
/// {@endtemplate}
|
||||
class DeleteAppCommand extends ShorebirdCommand
|
||||
with ShorebirdConfigMixin, ShorebirdValidationMixin {
|
||||
class DeleteAppCommand extends ShorebirdCommand {
|
||||
/// {@macro delete_app_command}
|
||||
DeleteAppCommand({super.buildCodePushClient}) {
|
||||
argParser
|
||||
@@ -48,7 +46,7 @@ Please use $consoleLink instead.''',
|
||||
);
|
||||
|
||||
try {
|
||||
await validatePreconditions(
|
||||
await shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: true,
|
||||
);
|
||||
} on PreconditionFailedException catch (e) {
|
||||
|
||||
@@ -5,8 +5,7 @@ import 'package:mason_logger/mason_logger.dart';
|
||||
import 'package:shorebird_cli/src/code_push_client_wrapper.dart';
|
||||
import 'package:shorebird_cli/src/command.dart';
|
||||
import 'package:shorebird_cli/src/logger.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_config_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validation_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validator.dart';
|
||||
import 'package:shorebird_code_push_client/shorebird_code_push_client.dart';
|
||||
|
||||
/// {@template list_apps_command}
|
||||
@@ -14,8 +13,7 @@ import 'package:shorebird_code_push_client/shorebird_code_push_client.dart';
|
||||
/// `shorebird apps list`
|
||||
/// List all apps using Shorebird.
|
||||
/// {@endtemplate}
|
||||
class ListAppsCommand extends ShorebirdCommand
|
||||
with ShorebirdConfigMixin, ShorebirdValidationMixin {
|
||||
class ListAppsCommand extends ShorebirdCommand {
|
||||
@override
|
||||
String get description => 'List all apps using Shorebird.';
|
||||
|
||||
@@ -35,7 +33,7 @@ Please use $consoleLink instead.''',
|
||||
);
|
||||
|
||||
try {
|
||||
await validatePreconditions(
|
||||
await shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: true,
|
||||
);
|
||||
} on PreconditionFailedException catch (e) {
|
||||
|
||||
@@ -7,7 +7,7 @@ import 'package:shorebird_cli/src/command.dart';
|
||||
import 'package:shorebird_cli/src/logger.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_build_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_config_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validation_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validator.dart';
|
||||
|
||||
/// {@template build_aar_command}
|
||||
///
|
||||
@@ -15,7 +15,7 @@ import 'package:shorebird_cli/src/shorebird_validation_mixin.dart';
|
||||
/// Build an Android aar file from your app.
|
||||
/// {@endtemplate}
|
||||
class BuildAarCommand extends ShorebirdCommand
|
||||
with ShorebirdConfigMixin, ShorebirdValidationMixin, ShorebirdBuildMixin {
|
||||
with ShorebirdConfigMixin, ShorebirdBuildMixin {
|
||||
BuildAarCommand() {
|
||||
// We would have a "target" option here, similar to what [BuildApkCommand]
|
||||
// and [BuildAabCommand] have, but target cannot currently be configured in
|
||||
@@ -39,7 +39,7 @@ class BuildAarCommand extends ShorebirdCommand
|
||||
@override
|
||||
Future<int> run() async {
|
||||
try {
|
||||
await validatePreconditions(
|
||||
await shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: true,
|
||||
checkShorebirdInitialized: true,
|
||||
);
|
||||
|
||||
@@ -7,7 +7,7 @@ import 'package:shorebird_cli/src/doctor.dart';
|
||||
import 'package:shorebird_cli/src/logger.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_build_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_config_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validation_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validator.dart';
|
||||
|
||||
/// {@template build_apk_command}
|
||||
///
|
||||
@@ -15,7 +15,7 @@ import 'package:shorebird_cli/src/shorebird_validation_mixin.dart';
|
||||
/// Build an Android APK file from your app.
|
||||
/// {@endtemplate}
|
||||
class BuildApkCommand extends ShorebirdCommand
|
||||
with ShorebirdConfigMixin, ShorebirdValidationMixin, ShorebirdBuildMixin {
|
||||
with ShorebirdConfigMixin, ShorebirdBuildMixin {
|
||||
/// {@macro build_apk_command}
|
||||
BuildApkCommand() {
|
||||
argParser
|
||||
@@ -39,8 +39,9 @@ class BuildApkCommand extends ShorebirdCommand
|
||||
@override
|
||||
Future<int> run() async {
|
||||
try {
|
||||
await validatePreconditions(
|
||||
await shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: true,
|
||||
checkShorebirdInitialized: true,
|
||||
validators: doctor.androidCommandValidators,
|
||||
);
|
||||
} on PreconditionFailedException catch (e) {
|
||||
|
||||
@@ -7,7 +7,7 @@ import 'package:shorebird_cli/src/doctor.dart';
|
||||
import 'package:shorebird_cli/src/logger.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_build_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_config_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validation_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validator.dart';
|
||||
|
||||
/// {@template build_app_bundle_command}
|
||||
///
|
||||
@@ -15,7 +15,7 @@ import 'package:shorebird_cli/src/shorebird_validation_mixin.dart';
|
||||
/// Build an Android App Bundle file from your app.
|
||||
/// {@endtemplate}
|
||||
class BuildAppBundleCommand extends ShorebirdCommand
|
||||
with ShorebirdConfigMixin, ShorebirdValidationMixin, ShorebirdBuildMixin {
|
||||
with ShorebirdConfigMixin, ShorebirdBuildMixin {
|
||||
/// {@macro build_app_bundle_command}
|
||||
BuildAppBundleCommand() {
|
||||
argParser
|
||||
@@ -39,8 +39,9 @@ class BuildAppBundleCommand extends ShorebirdCommand
|
||||
@override
|
||||
Future<int> run() async {
|
||||
try {
|
||||
await validatePreconditions(
|
||||
await shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: true,
|
||||
checkShorebirdInitialized: true,
|
||||
validators: doctor.androidCommandValidators,
|
||||
);
|
||||
} on PreconditionFailedException catch (e) {
|
||||
|
||||
@@ -7,7 +7,7 @@ import 'package:shorebird_cli/src/doctor.dart';
|
||||
import 'package:shorebird_cli/src/logger.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_build_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_config_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validation_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validator.dart';
|
||||
|
||||
/// {@template build_ipa_command}
|
||||
/// `shorebird build ipa`
|
||||
@@ -15,7 +15,7 @@ import 'package:shorebird_cli/src/shorebird_validation_mixin.dart';
|
||||
/// App Store submission.
|
||||
/// {@endtemplate}
|
||||
class BuildIpaCommand extends ShorebirdCommand
|
||||
with ShorebirdConfigMixin, ShorebirdValidationMixin, ShorebirdBuildMixin {
|
||||
with ShorebirdConfigMixin, ShorebirdBuildMixin {
|
||||
/// {@macro build_ipa_command}
|
||||
BuildIpaCommand() {
|
||||
argParser
|
||||
@@ -45,8 +45,9 @@ class BuildIpaCommand extends ShorebirdCommand
|
||||
@override
|
||||
Future<int> run() async {
|
||||
try {
|
||||
await validatePreconditions(
|
||||
await shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: true,
|
||||
checkShorebirdInitialized: true,
|
||||
validators: doctor.iosCommandValidators,
|
||||
);
|
||||
} on PreconditionFailedException catch (e) {
|
||||
|
||||
+3
-5
@@ -4,16 +4,14 @@ import 'package:mason_logger/mason_logger.dart';
|
||||
import 'package:shorebird_cli/src/auth/auth.dart';
|
||||
import 'package:shorebird_cli/src/command.dart';
|
||||
import 'package:shorebird_cli/src/logger.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_config_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_environment.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validation_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validator.dart';
|
||||
|
||||
/// {@template add_collaborators_command}
|
||||
/// `shorebird collaborators add`
|
||||
/// Add a new collaborator to a Shorebird app.
|
||||
/// {@endtemplate}
|
||||
class AddCollaboratorsCommand extends ShorebirdCommand
|
||||
with ShorebirdConfigMixin, ShorebirdValidationMixin {
|
||||
class AddCollaboratorsCommand extends ShorebirdCommand {
|
||||
/// {@macro add_collaborators_command}
|
||||
AddCollaboratorsCommand({super.buildCodePushClient}) {
|
||||
argParser
|
||||
@@ -39,7 +37,7 @@ class AddCollaboratorsCommand extends ShorebirdCommand
|
||||
@override
|
||||
Future<int>? run() async {
|
||||
try {
|
||||
await validatePreconditions(
|
||||
await shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: true,
|
||||
);
|
||||
} on PreconditionFailedException catch (e) {
|
||||
|
||||
+3
-5
@@ -5,17 +5,15 @@ import 'package:mason_logger/mason_logger.dart';
|
||||
import 'package:shorebird_cli/src/auth/auth.dart';
|
||||
import 'package:shorebird_cli/src/command.dart';
|
||||
import 'package:shorebird_cli/src/logger.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_config_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_environment.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validation_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validator.dart';
|
||||
import 'package:shorebird_code_push_client/shorebird_code_push_client.dart';
|
||||
|
||||
/// {@template delete_collaborators_command}
|
||||
/// `shorebird collaborators delete`
|
||||
/// Delete an existing collaborator from a Shorebird app.
|
||||
/// {@endtemplate}
|
||||
class DeleteCollaboratorsCommand extends ShorebirdCommand
|
||||
with ShorebirdConfigMixin, ShorebirdValidationMixin {
|
||||
class DeleteCollaboratorsCommand extends ShorebirdCommand {
|
||||
/// {@macro delete_collaborators_command}
|
||||
DeleteCollaboratorsCommand({super.buildCodePushClient}) {
|
||||
argParser
|
||||
@@ -42,7 +40,7 @@ class DeleteCollaboratorsCommand extends ShorebirdCommand
|
||||
@override
|
||||
Future<int>? run() async {
|
||||
try {
|
||||
await validatePreconditions(
|
||||
await shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: true,
|
||||
);
|
||||
} on PreconditionFailedException catch (e) {
|
||||
|
||||
+3
-5
@@ -5,17 +5,15 @@ import 'package:mason_logger/mason_logger.dart';
|
||||
import 'package:shorebird_cli/src/auth/auth.dart';
|
||||
import 'package:shorebird_cli/src/command.dart';
|
||||
import 'package:shorebird_cli/src/logger.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_config_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_environment.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validation_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validator.dart';
|
||||
import 'package:shorebird_code_push_client/shorebird_code_push_client.dart';
|
||||
|
||||
/// {@template list_collaborators_command}
|
||||
/// `shorebird collaborators list`
|
||||
/// List all collaborators for a Shorebird app.
|
||||
/// {@endtemplate}
|
||||
class ListCollaboratorsCommand extends ShorebirdCommand
|
||||
with ShorebirdConfigMixin, ShorebirdValidationMixin {
|
||||
class ListCollaboratorsCommand extends ShorebirdCommand {
|
||||
/// {@macro list_collaborators_command}
|
||||
ListCollaboratorsCommand({super.buildCodePushClient}) {
|
||||
argParser.addOption(
|
||||
@@ -38,7 +36,7 @@ class ListCollaboratorsCommand extends ShorebirdCommand
|
||||
@override
|
||||
Future<int>? run() async {
|
||||
try {
|
||||
await validatePreconditions(
|
||||
await shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: true,
|
||||
);
|
||||
} on PreconditionFailedException catch (e) {
|
||||
|
||||
@@ -11,7 +11,7 @@ import 'package:shorebird_cli/src/platform.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_config_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_create_app_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_environment.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validation_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validator.dart';
|
||||
import 'package:shorebird_cli/src/xcodebuild.dart';
|
||||
|
||||
/// {@template init_command}
|
||||
@@ -20,10 +20,7 @@ import 'package:shorebird_cli/src/xcodebuild.dart';
|
||||
/// Initialize Shorebird.
|
||||
/// {@endtemplate}
|
||||
class InitCommand extends ShorebirdCommand
|
||||
with
|
||||
ShorebirdConfigMixin,
|
||||
ShorebirdValidationMixin,
|
||||
ShorebirdCreateAppMixin {
|
||||
with ShorebirdConfigMixin, ShorebirdCreateAppMixin {
|
||||
/// {@macro init_command}
|
||||
InitCommand({super.buildCodePushClient}) {
|
||||
argParser.addFlag(
|
||||
@@ -43,7 +40,7 @@ class InitCommand extends ShorebirdCommand
|
||||
@override
|
||||
Future<int> run() async {
|
||||
try {
|
||||
await validatePreconditions(
|
||||
await shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: true,
|
||||
);
|
||||
} on PreconditionFailedException catch (e) {
|
||||
@@ -51,7 +48,7 @@ class InitCommand extends ShorebirdCommand
|
||||
}
|
||||
|
||||
try {
|
||||
if (!hasPubspecYaml) {
|
||||
if (!ShorebirdEnvironment.hasPubspecYaml) {
|
||||
logger.err('''
|
||||
Could not find a "pubspec.yaml".
|
||||
Please make sure you are running "shorebird init" from the root of your Flutter project.
|
||||
@@ -64,11 +61,11 @@ Please make sure you are running "shorebird init" from the root of your Flutter
|
||||
}
|
||||
|
||||
final force = results['force'] == true;
|
||||
if (force && hasShorebirdYaml) {
|
||||
if (force && ShorebirdEnvironment.hasShorebirdYaml) {
|
||||
ShorebirdEnvironment.getShorebirdYamlFile().deleteSync();
|
||||
}
|
||||
|
||||
if (hasShorebirdYaml) {
|
||||
if (ShorebirdEnvironment.hasShorebirdYaml) {
|
||||
logger.err('''
|
||||
A "shorebird.yaml" already exists.
|
||||
If you want to reinitialize Shorebird, please run "shorebird init --force".''');
|
||||
@@ -141,7 +138,9 @@ If you want to reinitialize Shorebird, please run "shorebird init --force".''');
|
||||
|
||||
addShorebirdYamlToProject(appId, flavors: flavors);
|
||||
|
||||
if (!pubspecContainsShorebirdYaml) addShorebirdYamlToPubspecAssets();
|
||||
if (!ShorebirdEnvironment.pubspecContainsShorebirdYaml) {
|
||||
addShorebirdYamlToPubspecAssets();
|
||||
}
|
||||
|
||||
await doctor.runValidators(doctor.allValidators, applyFixes: true);
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ import 'package:shorebird_cli/src/shorebird_artifact_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_build_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_config_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_environment.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validation_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validator.dart';
|
||||
import 'package:shorebird_code_push_client/shorebird_code_push_client.dart';
|
||||
|
||||
/// {@template patch_aar_command}
|
||||
@@ -25,11 +25,7 @@ import 'package:shorebird_code_push_client/shorebird_code_push_client.dart';
|
||||
/// Create a patch for an Android archive release.
|
||||
/// {@endtemplate}
|
||||
class PatchAarCommand extends ShorebirdCommand
|
||||
with
|
||||
ShorebirdConfigMixin,
|
||||
ShorebirdValidationMixin,
|
||||
ShorebirdBuildMixin,
|
||||
ShorebirdArtifactMixin {
|
||||
with ShorebirdConfigMixin, ShorebirdBuildMixin, ShorebirdArtifactMixin {
|
||||
/// {@macro patch_aar_command}
|
||||
PatchAarCommand({
|
||||
HashFunction? hashFn,
|
||||
@@ -91,7 +87,7 @@ of the Android app that is using this module.''',
|
||||
@override
|
||||
Future<int> run() async {
|
||||
try {
|
||||
await validatePreconditions(
|
||||
await shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: true,
|
||||
checkShorebirdInitialized: true,
|
||||
);
|
||||
|
||||
@@ -17,7 +17,7 @@ import 'package:shorebird_cli/src/shorebird_build_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_config_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_environment.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_release_version_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validation_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validator.dart';
|
||||
import 'package:shorebird_code_push_client/shorebird_code_push_client.dart';
|
||||
|
||||
/// {@template patch_android_command}
|
||||
@@ -28,7 +28,6 @@ import 'package:shorebird_code_push_client/shorebird_code_push_client.dart';
|
||||
class PatchAndroidCommand extends ShorebirdCommand
|
||||
with
|
||||
ShorebirdConfigMixin,
|
||||
ShorebirdValidationMixin,
|
||||
ShorebirdBuildMixin,
|
||||
ShorebirdReleaseVersionMixin {
|
||||
/// {@macro patch_android_command}
|
||||
@@ -81,7 +80,7 @@ class PatchAndroidCommand extends ShorebirdCommand
|
||||
@override
|
||||
Future<int> run() async {
|
||||
try {
|
||||
await validatePreconditions(
|
||||
await shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: true,
|
||||
checkShorebirdInitialized: true,
|
||||
validators: doctor.androidCommandValidators,
|
||||
|
||||
@@ -17,18 +17,14 @@ import 'package:shorebird_cli/src/shorebird_artifact_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_build_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_config_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_environment.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validation_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validator.dart';
|
||||
import 'package:shorebird_code_push_client/shorebird_code_push_client.dart';
|
||||
|
||||
/// {@template patch_ios_command}
|
||||
/// `shorebird patch ios-alpha` command.
|
||||
/// {@endtemplate}
|
||||
class PatchIosCommand extends ShorebirdCommand
|
||||
with
|
||||
ShorebirdConfigMixin,
|
||||
ShorebirdBuildMixin,
|
||||
ShorebirdValidationMixin,
|
||||
ShorebirdArtifactMixin {
|
||||
with ShorebirdConfigMixin, ShorebirdBuildMixin, ShorebirdArtifactMixin {
|
||||
/// {@macro patch_ios_command}
|
||||
PatchIosCommand({
|
||||
HashFunction? hashFn,
|
||||
@@ -72,7 +68,7 @@ class PatchIosCommand extends ShorebirdCommand
|
||||
@override
|
||||
Future<int> run() async {
|
||||
try {
|
||||
await validatePreconditions(
|
||||
await shorebirdValidator.validatePreconditions(
|
||||
checkShorebirdInitialized: true,
|
||||
checkUserIsAuthenticated: true,
|
||||
validators: doctor.iosCommandValidators,
|
||||
|
||||
@@ -14,15 +14,11 @@ import 'package:shorebird_cli/src/shorebird_artifact_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_build_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_config_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_environment.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validation_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validator.dart';
|
||||
import 'package:shorebird_code_push_client/shorebird_code_push_client.dart';
|
||||
|
||||
class PatchIosFrameworkCommand extends ShorebirdCommand
|
||||
with
|
||||
ShorebirdConfigMixin,
|
||||
ShorebirdValidationMixin,
|
||||
ShorebirdBuildMixin,
|
||||
ShorebirdArtifactMixin {
|
||||
with ShorebirdConfigMixin, ShorebirdBuildMixin, ShorebirdArtifactMixin {
|
||||
PatchIosFrameworkCommand({
|
||||
HashFunction? hashFn,
|
||||
}) : _hashFn = hashFn ?? ((m) => sha256.convert(m).toString()) {
|
||||
@@ -60,7 +56,7 @@ of the iOS app that is using this module.''',
|
||||
@override
|
||||
Future<int> run() async {
|
||||
try {
|
||||
await validatePreconditions(
|
||||
await shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: true,
|
||||
checkShorebirdInitialized: true,
|
||||
validators: doctor.iosCommandValidators,
|
||||
|
||||
@@ -13,16 +13,14 @@ import 'package:shorebird_cli/src/code_push_client_wrapper.dart';
|
||||
import 'package:shorebird_cli/src/command.dart';
|
||||
import 'package:shorebird_cli/src/ios_deploy.dart';
|
||||
import 'package:shorebird_cli/src/logger.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_config_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validation_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validator.dart';
|
||||
import 'package:shorebird_cli/src/third_party/flutter_tools/lib/flutter_tools.dart';
|
||||
import 'package:shorebird_code_push_client/shorebird_code_push_client.dart';
|
||||
|
||||
/// {@template preview_command}
|
||||
/// `shorebird preview` command.
|
||||
/// {@endtemplate}
|
||||
class PreviewCommand extends ShorebirdCommand
|
||||
with ShorebirdConfigMixin, ShorebirdValidationMixin {
|
||||
class PreviewCommand extends ShorebirdCommand {
|
||||
/// {@macro preview_command}
|
||||
PreviewCommand() {
|
||||
argParser
|
||||
@@ -60,7 +58,9 @@ class PreviewCommand extends ShorebirdCommand
|
||||
// TODO(bryanoltman): check preview target and run either
|
||||
// doctor.iosValidators or doctor.androidValidators as appropriate.
|
||||
try {
|
||||
await validatePreconditions(checkUserIsAuthenticated: true);
|
||||
await shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: true,
|
||||
);
|
||||
} on PreconditionFailedException catch (error) {
|
||||
return error.exitCode.code;
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ import 'package:shorebird_cli/src/shorebird_build_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_config_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_environment.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_release_version_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validation_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validator.dart';
|
||||
import 'package:shorebird_code_push_client/shorebird_code_push_client.dart';
|
||||
|
||||
/// {@template release_aar_command}
|
||||
@@ -22,7 +22,6 @@ import 'package:shorebird_code_push_client/shorebird_code_push_client.dart';
|
||||
class ReleaseAarCommand extends ShorebirdCommand
|
||||
with
|
||||
ShorebirdConfigMixin,
|
||||
ShorebirdValidationMixin,
|
||||
ShorebirdBuildMixin,
|
||||
ShorebirdReleaseVersionMixin,
|
||||
ShorebirdArtifactMixin {
|
||||
@@ -68,7 +67,7 @@ make smaller updates to your app.
|
||||
@override
|
||||
Future<int> run() async {
|
||||
try {
|
||||
await validatePreconditions(
|
||||
await shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: true,
|
||||
checkShorebirdInitialized: true,
|
||||
);
|
||||
|
||||
@@ -11,7 +11,7 @@ import 'package:shorebird_cli/src/shorebird_build_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_config_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_environment.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_release_version_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validation_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validator.dart';
|
||||
import 'package:shorebird_code_push_client/shorebird_code_push_client.dart';
|
||||
|
||||
/// {@template release_android_command}
|
||||
@@ -21,7 +21,6 @@ import 'package:shorebird_code_push_client/shorebird_code_push_client.dart';
|
||||
class ReleaseAndroidCommand extends ShorebirdCommand
|
||||
with
|
||||
ShorebirdConfigMixin,
|
||||
ShorebirdValidationMixin,
|
||||
ShorebirdBuildMixin,
|
||||
ShorebirdReleaseVersionMixin {
|
||||
/// {@macro release_android_command}
|
||||
@@ -67,7 +66,7 @@ make smaller updates to your app.
|
||||
@override
|
||||
Future<int> run() async {
|
||||
try {
|
||||
await validatePreconditions(
|
||||
await shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: true,
|
||||
checkShorebirdInitialized: true,
|
||||
validators: doctor.androidCommandValidators,
|
||||
|
||||
@@ -14,7 +14,7 @@ import 'package:shorebird_cli/src/shorebird_artifact_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_build_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_config_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_environment.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validation_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validator.dart';
|
||||
import 'package:shorebird_code_push_client/shorebird_code_push_client.dart';
|
||||
|
||||
/// {@template release_ios_command}
|
||||
@@ -22,11 +22,7 @@ import 'package:shorebird_code_push_client/shorebird_code_push_client.dart';
|
||||
/// Create new app releases for iOS.
|
||||
/// {@endtemplate}
|
||||
class ReleaseIosCommand extends ShorebirdCommand
|
||||
with
|
||||
ShorebirdBuildMixin,
|
||||
ShorebirdConfigMixin,
|
||||
ShorebirdArtifactMixin,
|
||||
ShorebirdValidationMixin {
|
||||
with ShorebirdBuildMixin, ShorebirdConfigMixin, ShorebirdArtifactMixin {
|
||||
/// {@macro release_ios_command}
|
||||
ReleaseIosCommand({
|
||||
IpaReader? ipaReader,
|
||||
@@ -64,7 +60,7 @@ make smaller updates to your app.
|
||||
@override
|
||||
Future<int> run() async {
|
||||
try {
|
||||
await validatePreconditions(
|
||||
await shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: true,
|
||||
checkShorebirdInitialized: true,
|
||||
validators: doctor.iosCommandValidators,
|
||||
|
||||
@@ -12,11 +12,11 @@ import 'package:shorebird_cli/src/logger.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_build_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_config_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_environment.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validation_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validator.dart';
|
||||
import 'package:shorebird_code_push_client/shorebird_code_push_client.dart';
|
||||
|
||||
class ReleaseIosFrameworkCommand extends ShorebirdCommand
|
||||
with ShorebirdConfigMixin, ShorebirdValidationMixin, ShorebirdBuildMixin {
|
||||
with ShorebirdConfigMixin, ShorebirdBuildMixin {
|
||||
ReleaseIosFrameworkCommand() {
|
||||
argParser
|
||||
..addOption(
|
||||
@@ -44,7 +44,7 @@ of the iOS app that is using this module.''',
|
||||
@override
|
||||
Future<int> run() async {
|
||||
try {
|
||||
await validatePreconditions(
|
||||
await shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: true,
|
||||
checkShorebirdInitialized: true,
|
||||
validators: doctor.iosCommandValidators,
|
||||
|
||||
@@ -6,9 +6,8 @@ import 'package:shorebird_cli/src/auth/auth.dart';
|
||||
import 'package:shorebird_cli/src/command.dart';
|
||||
import 'package:shorebird_cli/src/config/shorebird_yaml.dart';
|
||||
import 'package:shorebird_cli/src/logger.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_config_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_environment.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validation_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validator.dart';
|
||||
import 'package:shorebird_code_push_client/shorebird_code_push_client.dart';
|
||||
|
||||
/// {@template delete_releases_command}
|
||||
@@ -16,8 +15,7 @@ import 'package:shorebird_code_push_client/shorebird_code_push_client.dart';
|
||||
/// `shorebird releases delete`
|
||||
/// Delete the specified release.
|
||||
/// {@endtemplate}
|
||||
class DeleteReleasesCommand extends ShorebirdCommand
|
||||
with ShorebirdConfigMixin, ShorebirdValidationMixin {
|
||||
class DeleteReleasesCommand extends ShorebirdCommand {
|
||||
/// {@macro delete_releases_command}
|
||||
DeleteReleasesCommand({super.buildCodePushClient}) {
|
||||
argParser
|
||||
@@ -40,7 +38,7 @@ class DeleteReleasesCommand extends ShorebirdCommand
|
||||
@override
|
||||
Future<int> run() async {
|
||||
try {
|
||||
await validatePreconditions(
|
||||
await shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: true,
|
||||
checkShorebirdInitialized: true,
|
||||
);
|
||||
|
||||
@@ -4,9 +4,8 @@ import 'package:shorebird_cli/src/auth/auth.dart';
|
||||
import 'package:shorebird_cli/src/command.dart';
|
||||
import 'package:shorebird_cli/src/config/shorebird_yaml.dart';
|
||||
import 'package:shorebird_cli/src/logger.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_config_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_environment.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validation_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validator.dart';
|
||||
import 'package:shorebird_code_push_client/shorebird_code_push_client.dart';
|
||||
|
||||
/// {@template list_releases_command}
|
||||
@@ -14,8 +13,7 @@ import 'package:shorebird_code_push_client/shorebird_code_push_client.dart';
|
||||
/// `shorebird releases list`
|
||||
/// List all releases for this app.
|
||||
/// {@endtemplate}
|
||||
class ListReleasesCommand extends ShorebirdCommand
|
||||
with ShorebirdConfigMixin, ShorebirdValidationMixin {
|
||||
class ListReleasesCommand extends ShorebirdCommand {
|
||||
/// {@macro list_releases_command}
|
||||
ListReleasesCommand({super.buildCodePushClient}) {
|
||||
argParser.addOption(
|
||||
@@ -40,7 +38,7 @@ Please use $consoleLink instead.''',
|
||||
);
|
||||
|
||||
try {
|
||||
await validatePreconditions(
|
||||
await shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: true,
|
||||
checkShorebirdInitialized: true,
|
||||
);
|
||||
|
||||
@@ -6,15 +6,13 @@ import 'package:shorebird_cli/src/command.dart';
|
||||
import 'package:shorebird_cli/src/doctor.dart';
|
||||
import 'package:shorebird_cli/src/logger.dart';
|
||||
import 'package:shorebird_cli/src/process.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_config_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validation_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validator.dart';
|
||||
|
||||
/// {@template run_command}
|
||||
/// `shorebird run`
|
||||
/// Run the Flutter application.
|
||||
/// {@endtemplate}
|
||||
class RunCommand extends ShorebirdCommand
|
||||
with ShorebirdConfigMixin, ShorebirdValidationMixin {
|
||||
class RunCommand extends ShorebirdCommand {
|
||||
/// {@macro run_command}
|
||||
RunCommand({super.buildCodePushClient}) {
|
||||
argParser
|
||||
@@ -63,7 +61,7 @@ Please use "shorebird preview" instead.''',
|
||||
// TODO(bryanoltman): check run target and run either
|
||||
// doctor.iosValidators or doctor.androidValidators as appropriate.
|
||||
try {
|
||||
await validatePreconditions(
|
||||
await shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: true,
|
||||
validators: doctor.allValidators,
|
||||
);
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import 'package:mason_logger/mason_logger.dart';
|
||||
import 'package:scoped/scoped.dart';
|
||||
|
||||
// A reference to a [Logger] instance.
|
||||
/// A reference to a [Logger] instance.
|
||||
final loggerRef = create(Logger.new);
|
||||
|
||||
// The [Logger] instance available in the current zone.
|
||||
/// The [Logger] instance available in the current zone.
|
||||
Logger get logger => read(loggerRef);
|
||||
|
||||
@@ -9,30 +9,11 @@ import 'package:yaml/yaml.dart';
|
||||
import 'package:yaml_edit/yaml_edit.dart';
|
||||
|
||||
mixin ShorebirdConfigMixin on ShorebirdCommand {
|
||||
bool get hasShorebirdYaml =>
|
||||
ShorebirdEnvironment.getShorebirdYamlFile().existsSync();
|
||||
|
||||
bool get hasPubspecYaml => ShorebirdEnvironment.getPubspecYaml() != null;
|
||||
|
||||
bool get isShorebirdInitialized {
|
||||
return hasShorebirdYaml && pubspecContainsShorebirdYaml;
|
||||
}
|
||||
|
||||
bool get pubspecContainsShorebirdYaml {
|
||||
final file = File(p.join(Directory.current.path, 'pubspec.yaml'));
|
||||
final pubspecContents = file.readAsStringSync();
|
||||
final yaml = loadYaml(pubspecContents, sourceUrl: file.uri) as Map;
|
||||
if (!yaml.containsKey('flutter')) return false;
|
||||
if (!(yaml['flutter'] as Map).containsKey('assets')) return false;
|
||||
final assets = (yaml['flutter'] as Map)['assets'] as List;
|
||||
return assets.contains('shorebird.yaml');
|
||||
}
|
||||
|
||||
/// Returns the Android package name from the pubspec.yaml file of a Flutter
|
||||
/// module.
|
||||
String? get androidPackageName {
|
||||
final pubspec = ShorebirdEnvironment.getPubspecYaml()!;
|
||||
final module = pubspec.flutter?['module'] as Map?;
|
||||
final pubspec = ShorebirdEnvironment.getPubspecYaml();
|
||||
final module = pubspec?.flutter?['module'] as Map?;
|
||||
return module?['androidPackage'] as String?;
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import 'package:pubspec_parse/pubspec_parse.dart';
|
||||
import 'package:shorebird_cli/src/config/shorebird_yaml.dart';
|
||||
import 'package:shorebird_cli/src/platform.dart';
|
||||
import 'package:shorebird_code_push_client/shorebird_code_push_client.dart';
|
||||
import 'package:yaml/yaml.dart';
|
||||
|
||||
abstract class ShorebirdEnvironment {
|
||||
/// Environment variables from [Platform.environment].
|
||||
@@ -95,6 +96,28 @@ abstract class ShorebirdEnvironment {
|
||||
return checkedYamlDecode(yaml, (m) => ShorebirdYaml.fromJson(m!));
|
||||
}
|
||||
|
||||
static bool get isShorebirdInitialized {
|
||||
return hasShorebirdYaml && pubspecContainsShorebirdYaml;
|
||||
}
|
||||
|
||||
static bool get hasShorebirdYaml {
|
||||
return ShorebirdEnvironment.getShorebirdYamlFile().existsSync();
|
||||
}
|
||||
|
||||
static bool get hasPubspecYaml {
|
||||
return ShorebirdEnvironment.getPubspecYaml() != null;
|
||||
}
|
||||
|
||||
static bool get pubspecContainsShorebirdYaml {
|
||||
final file = File(p.join(Directory.current.path, 'pubspec.yaml'));
|
||||
final pubspecContents = file.readAsStringSync();
|
||||
final yaml = loadYaml(pubspecContents, sourceUrl: file.uri) as Map;
|
||||
if (!yaml.containsKey('flutter')) return false;
|
||||
if (!(yaml['flutter'] as Map).containsKey('assets')) return false;
|
||||
final assets = (yaml['flutter'] as Map)['assets'] as List;
|
||||
return assets.contains('shorebird.yaml');
|
||||
}
|
||||
|
||||
/// The `pubspec.yaml` file for this project, parsed into a [Pubspec] object.
|
||||
///
|
||||
/// Returns `null` if the file does not exist.
|
||||
|
||||
+17
-3
@@ -1,9 +1,10 @@
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:mason_logger/mason_logger.dart';
|
||||
import 'package:scoped/scoped.dart';
|
||||
import 'package:shorebird_cli/src/auth/auth.dart';
|
||||
import 'package:shorebird_cli/src/logger.dart';
|
||||
import 'package:shorebird_cli/src/platform.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_config_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_environment.dart';
|
||||
import 'package:shorebird_cli/src/validators/validators.dart';
|
||||
|
||||
abstract interface class PreconditionFailedException implements Exception {
|
||||
@@ -31,7 +32,19 @@ class UnsupportedOperatingSystemException
|
||||
ExitCode get exitCode => ExitCode.unavailable;
|
||||
}
|
||||
|
||||
mixin ShorebirdValidationMixin on ShorebirdConfigMixin {
|
||||
/// A reference to a [ShorebirdValidator] instance.
|
||||
final shorebirdValidatorRef = create(ShorebirdValidator.new);
|
||||
|
||||
/// The [ShorebirdValidator] instance available in the current zone.
|
||||
ShorebirdValidator get shorebirdValidator => read(shorebirdValidatorRef);
|
||||
|
||||
/// {@template shorebird_validator}
|
||||
/// A class that provides common validation functionality for commands.
|
||||
/// {@endtemplate}
|
||||
class ShorebirdValidator {
|
||||
/// {@macro shorebird_validator}
|
||||
const ShorebirdValidator();
|
||||
|
||||
/// Checks common preconditions for running a command and throws an
|
||||
/// appropriate [PreconditionFailedException] if any of them fail.
|
||||
Future<void> validatePreconditions({
|
||||
@@ -60,7 +73,8 @@ mixin ShorebirdValidationMixin on ShorebirdConfigMixin {
|
||||
throw UserNotAuthorizedException();
|
||||
}
|
||||
|
||||
if (checkShorebirdInitialized && !isShorebirdInitialized) {
|
||||
if (checkShorebirdInitialized &&
|
||||
!ShorebirdEnvironment.isShorebirdInitialized) {
|
||||
logger.err(
|
||||
'Shorebird is not initialized. Did you run "shorebird init"?',
|
||||
);
|
||||
+27
-10
@@ -5,6 +5,7 @@ import 'package:scoped/scoped.dart';
|
||||
import 'package:shorebird_cli/src/auth/auth.dart';
|
||||
import 'package:shorebird_cli/src/commands/account/account.dart';
|
||||
import 'package:shorebird_cli/src/logger.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validator.dart';
|
||||
import 'package:shorebird_code_push_client/shorebird_code_push_client.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
@@ -18,6 +19,8 @@ class _MockLogger extends Mock implements Logger {}
|
||||
|
||||
class _MockProgress extends Mock implements Progress {}
|
||||
|
||||
class _MockShorebirdValidator extends Mock implements ShorebirdValidator {}
|
||||
|
||||
void main() {
|
||||
group(DowngradeAccountCommand, () {
|
||||
const noSubscriptionUser = User(id: 1, email: 'tester1@shorebird.dev');
|
||||
@@ -32,6 +35,7 @@ void main() {
|
||||
late http.Client httpClient;
|
||||
late Logger logger;
|
||||
late Progress progress;
|
||||
late ShorebirdValidator shorebirdValidator;
|
||||
late DowngradeAccountCommand command;
|
||||
|
||||
R runWithOverrides<R>(R Function() body) {
|
||||
@@ -39,7 +43,8 @@ void main() {
|
||||
body,
|
||||
values: {
|
||||
authRef.overrideWith(() => auth),
|
||||
loggerRef.overrideWith(() => logger)
|
||||
loggerRef.overrideWith(() => logger),
|
||||
shorebirdValidatorRef.overrideWith(() => shorebirdValidator),
|
||||
},
|
||||
);
|
||||
}
|
||||
@@ -50,10 +55,15 @@ void main() {
|
||||
httpClient = _MockHttpClient();
|
||||
logger = _MockLogger();
|
||||
progress = _MockProgress();
|
||||
shorebirdValidator = _MockShorebirdValidator();
|
||||
|
||||
when(() => auth.client).thenReturn(httpClient);
|
||||
|
||||
when(() => logger.progress(any())).thenReturn(progress);
|
||||
when(
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: any(named: 'checkUserIsAuthenticated'),
|
||||
),
|
||||
).thenAnswer((_) async {});
|
||||
|
||||
command = runWithOverrides(
|
||||
() => DowngradeAccountCommand(
|
||||
@@ -67,18 +77,25 @@ void main() {
|
||||
);
|
||||
});
|
||||
|
||||
test('returns a non-empty description', () {
|
||||
test('has a description', () {
|
||||
expect(command.description, isNotEmpty);
|
||||
});
|
||||
|
||||
test('prints an error if the user is not logged in', () async {
|
||||
when(() => auth.isAuthenticated).thenReturn(false);
|
||||
|
||||
final result = await runWithOverrides(command.run);
|
||||
|
||||
expect(result, ExitCode.noUser.code);
|
||||
test('exits when validation fails', () async {
|
||||
final exception = ValidationFailedException();
|
||||
when(
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: any(named: 'checkUserIsAuthenticated'),
|
||||
),
|
||||
).thenThrow(exception);
|
||||
await expectLater(
|
||||
runWithOverrides(command.run),
|
||||
completion(equals(exception.exitCode.code)),
|
||||
);
|
||||
verify(
|
||||
() => logger.err(any(that: contains('You must be logged in'))),
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: true,
|
||||
),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
|
||||
+33
-14
@@ -5,6 +5,7 @@ import 'package:scoped/scoped.dart';
|
||||
import 'package:shorebird_cli/src/auth/auth.dart';
|
||||
import 'package:shorebird_cli/src/commands/account/account.dart';
|
||||
import 'package:shorebird_cli/src/logger.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validator.dart';
|
||||
import 'package:shorebird_code_push_client/shorebird_code_push_client.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
@@ -18,6 +19,8 @@ class _MockLogger extends Mock implements Logger {}
|
||||
|
||||
class _MockProgress extends Mock implements Progress {}
|
||||
|
||||
class _MockShorebirdValidator extends Mock implements ShorebirdValidator {}
|
||||
|
||||
class _MockUser extends Mock implements User {}
|
||||
|
||||
void main() {
|
||||
@@ -28,8 +31,8 @@ void main() {
|
||||
late http.Client httpClient;
|
||||
late Logger logger;
|
||||
late Progress progress;
|
||||
late ShorebirdValidator shorebirdValidator;
|
||||
late User user;
|
||||
|
||||
late UpgradeAccountCommand command;
|
||||
|
||||
group(UpgradeAccountCommand, () {
|
||||
@@ -38,7 +41,8 @@ void main() {
|
||||
body,
|
||||
values: {
|
||||
authRef.overrideWith(() => auth),
|
||||
loggerRef.overrideWith(() => logger)
|
||||
loggerRef.overrideWith(() => logger),
|
||||
shorebirdValidatorRef.overrideWith(() => shorebirdValidator),
|
||||
},
|
||||
);
|
||||
}
|
||||
@@ -49,19 +53,27 @@ void main() {
|
||||
httpClient = _MockHttpClient();
|
||||
logger = _MockLogger();
|
||||
progress = _MockProgress();
|
||||
shorebirdValidator = _MockShorebirdValidator();
|
||||
user = _MockUser();
|
||||
|
||||
when(() => auth.client).thenReturn(httpClient);
|
||||
when(() => auth.isAuthenticated).thenReturn(true);
|
||||
|
||||
when(() => codePushClient.createPaymentLink())
|
||||
.thenAnswer((_) async => paymentLink);
|
||||
when(
|
||||
() => codePushClient.createPaymentLink(),
|
||||
).thenAnswer((_) async => paymentLink);
|
||||
when(() => codePushClient.getCurrentUser()).thenAnswer((_) async => user);
|
||||
|
||||
when(() => logger.err(any())).thenReturn(null);
|
||||
when(() => logger.info(any())).thenReturn(null);
|
||||
when(() => logger.progress(any())).thenReturn(progress);
|
||||
|
||||
when(
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: any(named: 'checkUserIsAuthenticated'),
|
||||
),
|
||||
).thenAnswer((_) async {});
|
||||
|
||||
when(() => user.hasActiveSubscription).thenReturn(false);
|
||||
|
||||
command = runWithOverrides(
|
||||
@@ -77,23 +89,30 @@ void main() {
|
||||
expect(command.description, isNotEmpty);
|
||||
});
|
||||
|
||||
test('exits with code 67 when user is not logged in', () async {
|
||||
when(() => auth.isAuthenticated).thenReturn(false);
|
||||
|
||||
final result = await runWithOverrides(command.run);
|
||||
|
||||
expect(result, ExitCode.noUser.code);
|
||||
|
||||
test('exits when validation fails', () async {
|
||||
final exception = ValidationFailedException();
|
||||
when(
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: any(named: 'checkUserIsAuthenticated'),
|
||||
),
|
||||
).thenThrow(exception);
|
||||
await expectLater(
|
||||
runWithOverrides(command.run),
|
||||
completion(equals(exception.exitCode.code)),
|
||||
);
|
||||
verify(
|
||||
() => logger.err(any(that: contains('You must be logged in to run'))),
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: true,
|
||||
),
|
||||
).called(1);
|
||||
verifyNever(() => codePushClient.createPaymentLink());
|
||||
});
|
||||
|
||||
test('exits with code 70 when getCurrentUser throws an exception',
|
||||
() async {
|
||||
when(() => codePushClient.getCurrentUser())
|
||||
.thenThrow(Exception('oh no!'));
|
||||
when(
|
||||
() => codePushClient.getCurrentUser(),
|
||||
).thenThrow(Exception('oh no!'));
|
||||
|
||||
final result = await runWithOverrides(command.run);
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import 'package:scoped/scoped.dart';
|
||||
import 'package:shorebird_cli/src/auth/auth.dart';
|
||||
import 'package:shorebird_cli/src/commands/commands.dart';
|
||||
import 'package:shorebird_cli/src/logger.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validator.dart';
|
||||
import 'package:shorebird_code_push_client/shorebird_code_push_client.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
@@ -19,6 +20,8 @@ class _MockCodePushClient extends Mock implements CodePushClient {}
|
||||
|
||||
class _MockLogger extends Mock implements Logger {}
|
||||
|
||||
class _MockShorebirdValidator extends Mock implements ShorebirdValidator {}
|
||||
|
||||
void main() {
|
||||
group(CreateAppCommand, () {
|
||||
const appId = 'app-id';
|
||||
@@ -29,6 +32,7 @@ void main() {
|
||||
late Auth auth;
|
||||
late Logger logger;
|
||||
late CodePushClient codePushClient;
|
||||
late ShorebirdValidator shorebirdValidator;
|
||||
late CreateAppCommand command;
|
||||
|
||||
R runWithOverrides<R>(R Function() body) {
|
||||
@@ -36,7 +40,8 @@ void main() {
|
||||
body,
|
||||
values: {
|
||||
authRef.overrideWith(() => auth),
|
||||
loggerRef.overrideWith(() => logger)
|
||||
loggerRef.overrideWith(() => logger),
|
||||
shorebirdValidatorRef.overrideWith(() => shorebirdValidator),
|
||||
},
|
||||
);
|
||||
}
|
||||
@@ -47,9 +52,15 @@ void main() {
|
||||
auth = _MockAuth();
|
||||
logger = _MockLogger();
|
||||
codePushClient = _MockCodePushClient();
|
||||
shorebirdValidator = _MockShorebirdValidator();
|
||||
|
||||
when(() => auth.client).thenReturn(httpClient);
|
||||
when(() => auth.isAuthenticated).thenReturn(true);
|
||||
when(
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: any(named: 'checkUserIsAuthenticated'),
|
||||
),
|
||||
).thenAnswer((_) async {});
|
||||
|
||||
command = runWithOverrides(
|
||||
() => CreateAppCommand(
|
||||
@@ -63,14 +74,26 @@ void main() {
|
||||
)..testArgResults = argResults;
|
||||
});
|
||||
|
||||
test('returns correct description', () {
|
||||
test('has a description', () {
|
||||
expect(command.description, equals('Create a new app on Shorebird.'));
|
||||
});
|
||||
|
||||
test('returns no user error when not logged in', () async {
|
||||
when(() => auth.isAuthenticated).thenReturn(false);
|
||||
final result = await runWithOverrides(command.run);
|
||||
expect(result, ExitCode.noUser.code);
|
||||
test('exits when validation fails', () async {
|
||||
final exception = ValidationFailedException();
|
||||
when(
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: any(named: 'checkUserIsAuthenticated'),
|
||||
),
|
||||
).thenThrow(exception);
|
||||
await expectLater(
|
||||
runWithOverrides(command.run),
|
||||
completion(equals(exception.exitCode.code)),
|
||||
);
|
||||
verify(
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: true,
|
||||
),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test('prompts for app name when not provided', () async {
|
||||
|
||||
@@ -6,6 +6,7 @@ import 'package:scoped/scoped.dart';
|
||||
import 'package:shorebird_cli/src/auth/auth.dart';
|
||||
import 'package:shorebird_cli/src/commands/commands.dart';
|
||||
import 'package:shorebird_cli/src/logger.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validator.dart';
|
||||
import 'package:shorebird_code_push_client/shorebird_code_push_client.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
@@ -19,6 +20,8 @@ class _MockCodePushClient extends Mock implements CodePushClient {}
|
||||
|
||||
class _MockLogger extends Mock implements Logger {}
|
||||
|
||||
class _MockShorebirdValidator extends Mock implements ShorebirdValidator {}
|
||||
|
||||
void main() {
|
||||
group(DeleteAppCommand, () {
|
||||
const appId = 'example';
|
||||
@@ -28,6 +31,7 @@ void main() {
|
||||
late Auth auth;
|
||||
late Logger logger;
|
||||
late CodePushClient codePushClient;
|
||||
late ShorebirdValidator shorebirdValidator;
|
||||
late DeleteAppCommand command;
|
||||
|
||||
R runWithOverrides<R>(R Function() body) {
|
||||
@@ -35,7 +39,8 @@ void main() {
|
||||
body,
|
||||
values: {
|
||||
authRef.overrideWith(() => auth),
|
||||
loggerRef.overrideWith(() => logger)
|
||||
loggerRef.overrideWith(() => logger),
|
||||
shorebirdValidatorRef.overrideWith(() => shorebirdValidator),
|
||||
},
|
||||
);
|
||||
}
|
||||
@@ -46,9 +51,15 @@ void main() {
|
||||
auth = _MockAuth();
|
||||
logger = _MockLogger();
|
||||
codePushClient = _MockCodePushClient();
|
||||
shorebirdValidator = _MockShorebirdValidator();
|
||||
|
||||
when(() => auth.isAuthenticated).thenReturn(true);
|
||||
when(() => auth.client).thenReturn(httpClient);
|
||||
when(
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: any(named: 'checkUserIsAuthenticated'),
|
||||
),
|
||||
).thenAnswer((_) async {});
|
||||
|
||||
command = runWithOverrides(
|
||||
() => DeleteAppCommand(
|
||||
@@ -62,17 +73,29 @@ void main() {
|
||||
)..testArgResults = argResults;
|
||||
});
|
||||
|
||||
test('returns correct description', () {
|
||||
test('has a description', () {
|
||||
expect(
|
||||
command.description,
|
||||
equals('Delete an existing app on Shorebird.'),
|
||||
);
|
||||
});
|
||||
|
||||
test('returns no user error when not logged in', () async {
|
||||
when(() => auth.isAuthenticated).thenReturn(false);
|
||||
final result = await runWithOverrides(command.run);
|
||||
expect(result, ExitCode.noUser.code);
|
||||
test('exits when validation fails', () async {
|
||||
final exception = ValidationFailedException();
|
||||
when(
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: any(named: 'checkUserIsAuthenticated'),
|
||||
),
|
||||
).thenThrow(exception);
|
||||
await expectLater(
|
||||
runWithOverrides(command.run),
|
||||
completion(equals(exception.exitCode.code)),
|
||||
);
|
||||
verify(
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: true,
|
||||
),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test('prompts for app-id when not provided', () async {
|
||||
|
||||
@@ -5,6 +5,7 @@ import 'package:shorebird_cli/src/auth/auth.dart';
|
||||
import 'package:shorebird_cli/src/code_push_client_wrapper.dart';
|
||||
import 'package:shorebird_cli/src/commands/commands.dart';
|
||||
import 'package:shorebird_cli/src/logger.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validator.dart';
|
||||
import 'package:shorebird_code_push_client/shorebird_code_push_client.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
@@ -15,11 +16,14 @@ class _MockCodePushClientWrapper extends Mock
|
||||
|
||||
class _MockLogger extends Mock implements Logger {}
|
||||
|
||||
class _MockShorebirdValidator extends Mock implements ShorebirdValidator {}
|
||||
|
||||
void main() {
|
||||
group(ListAppsCommand, () {
|
||||
late Auth auth;
|
||||
late CodePushClientWrapper codePushClientWrapper;
|
||||
late Logger logger;
|
||||
late ShorebirdValidator shorebirdValidator;
|
||||
late ListAppsCommand command;
|
||||
|
||||
R runWithOverrides<R>(R Function() body) {
|
||||
@@ -28,7 +32,8 @@ void main() {
|
||||
values: {
|
||||
authRef.overrideWith(() => auth),
|
||||
codePushClientWrapperRef.overrideWith(() => codePushClientWrapper),
|
||||
loggerRef.overrideWith(() => logger)
|
||||
loggerRef.overrideWith(() => logger),
|
||||
shorebirdValidatorRef.overrideWith(() => shorebirdValidator),
|
||||
},
|
||||
);
|
||||
}
|
||||
@@ -37,18 +42,37 @@ void main() {
|
||||
auth = _MockAuth();
|
||||
codePushClientWrapper = _MockCodePushClientWrapper();
|
||||
logger = _MockLogger();
|
||||
shorebirdValidator = _MockShorebirdValidator();
|
||||
command = ListAppsCommand();
|
||||
|
||||
when(() => auth.isAuthenticated).thenReturn(true);
|
||||
when(
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: any(named: 'checkUserIsAuthenticated'),
|
||||
),
|
||||
).thenAnswer((_) async {});
|
||||
});
|
||||
|
||||
test('description is correct', () {
|
||||
test('has a description', () {
|
||||
expect(command.description, equals('List all apps using Shorebird.'));
|
||||
});
|
||||
|
||||
test('returns ExitCode.noUser when not logged in', () async {
|
||||
when(() => auth.isAuthenticated).thenReturn(false);
|
||||
expect(await runWithOverrides(command.run), ExitCode.noUser.code);
|
||||
test('exits when validation fails', () async {
|
||||
final exception = ValidationFailedException();
|
||||
when(
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: any(named: 'checkUserIsAuthenticated'),
|
||||
),
|
||||
).thenThrow(exception);
|
||||
await expectLater(
|
||||
runWithOverrides(command.run),
|
||||
completion(equals(exception.exitCode.code)),
|
||||
);
|
||||
verify(
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: true,
|
||||
),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test('returns ExitCode.success when apps are empty', () async {
|
||||
|
||||
@@ -10,6 +10,7 @@ import 'package:shorebird_cli/src/auth/auth.dart';
|
||||
import 'package:shorebird_cli/src/commands/build/build.dart';
|
||||
import 'package:shorebird_cli/src/logger.dart';
|
||||
import 'package:shorebird_cli/src/process.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validator.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
class _MockArgResults extends Mock implements ArgResults {}
|
||||
@@ -26,6 +27,8 @@ class _MockProgress extends Mock implements Progress {}
|
||||
|
||||
class _MockShorebirdProcess extends Mock implements ShorebirdProcess {}
|
||||
|
||||
class _MockShorebirdValidator extends Mock implements ShorebirdValidator {}
|
||||
|
||||
void main() {
|
||||
group(BuildAarCommand, () {
|
||||
const appId = 'test-app-id';
|
||||
@@ -61,6 +64,7 @@ flutter:
|
||||
late Progress progress;
|
||||
late ShorebirdProcess shorebirdProcess;
|
||||
late ShorebirdProcessResult processResult;
|
||||
late ShorebirdValidator shorebirdValidator;
|
||||
late BuildAarCommand command;
|
||||
|
||||
R runWithOverrides<R>(R Function() body) {
|
||||
@@ -70,6 +74,7 @@ flutter:
|
||||
authRef.overrideWith(() => auth),
|
||||
loggerRef.overrideWith(() => logger),
|
||||
processRef.overrideWith(() => shorebirdProcess),
|
||||
shorebirdValidatorRef.overrideWith(() => shorebirdValidator),
|
||||
},
|
||||
);
|
||||
}
|
||||
@@ -95,6 +100,7 @@ flutter:
|
||||
processResult = _MockProcessResult();
|
||||
progress = _MockProgress();
|
||||
shorebirdProcess = _MockShorebirdProcess();
|
||||
shorebirdValidator = _MockShorebirdValidator();
|
||||
|
||||
when(() => argResults['build-number']).thenReturn(buildNumber);
|
||||
when(() => argResults.rest).thenReturn([]);
|
||||
@@ -112,22 +118,38 @@ flutter:
|
||||
return processResult;
|
||||
});
|
||||
|
||||
when(
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: any(named: 'checkUserIsAuthenticated'),
|
||||
checkShorebirdInitialized: any(named: 'checkShorebirdInitialized'),
|
||||
),
|
||||
).thenAnswer((_) async {});
|
||||
|
||||
command = runWithOverrides(BuildAarCommand.new)
|
||||
..testArgResults = argResults;
|
||||
});
|
||||
|
||||
test('has correct description', () {
|
||||
test('has a description', () {
|
||||
expect(command.description, isNotEmpty);
|
||||
});
|
||||
|
||||
test('exits with no user when not logged in', () async {
|
||||
when(() => auth.isAuthenticated).thenReturn(false);
|
||||
|
||||
final result = await runWithOverrides(command.run);
|
||||
expect(result, equals(ExitCode.noUser.code));
|
||||
|
||||
test('exits when validation fails', () async {
|
||||
final exception = ValidationFailedException();
|
||||
when(
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: any(named: 'checkUserIsAuthenticated'),
|
||||
checkShorebirdInitialized: any(named: 'checkShorebirdInitialized'),
|
||||
),
|
||||
).thenThrow(exception);
|
||||
await expectLater(
|
||||
runWithOverrides(command.run),
|
||||
completion(equals(exception.exitCode.code)),
|
||||
);
|
||||
verify(
|
||||
() => logger.err(any(that: contains('You must be logged in to run'))),
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: true,
|
||||
checkShorebirdInitialized: true,
|
||||
),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ import 'package:shorebird_cli/src/commands/build/build.dart';
|
||||
import 'package:shorebird_cli/src/doctor.dart';
|
||||
import 'package:shorebird_cli/src/logger.dart';
|
||||
import 'package:shorebird_cli/src/process.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validator.dart';
|
||||
import 'package:shorebird_cli/src/validators/validators.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
@@ -33,6 +34,8 @@ class _MockShorebirdFlutterValidator extends Mock
|
||||
|
||||
class _MockShorebirdProcess extends Mock implements ShorebirdProcess {}
|
||||
|
||||
class _MockShorebirdValidator extends Mock implements ShorebirdValidator {}
|
||||
|
||||
void main() {
|
||||
group(BuildApkCommand, () {
|
||||
late ArgResults argResults;
|
||||
@@ -44,6 +47,7 @@ void main() {
|
||||
late BuildApkCommand command;
|
||||
late ShorebirdFlutterValidator flutterValidator;
|
||||
late ShorebirdProcess shorebirdProcess;
|
||||
late ShorebirdValidator shorebirdValidator;
|
||||
|
||||
R runWithOverrides<R>(R Function() body) {
|
||||
return runScoped(
|
||||
@@ -53,6 +57,7 @@ void main() {
|
||||
doctorRef.overrideWith(() => doctor),
|
||||
loggerRef.overrideWith(() => logger),
|
||||
processRef.overrideWith(() => shorebirdProcess),
|
||||
shorebirdValidatorRef.overrideWith(() => shorebirdValidator),
|
||||
},
|
||||
);
|
||||
}
|
||||
@@ -66,6 +71,7 @@ void main() {
|
||||
shorebirdProcess = _MockShorebirdProcess();
|
||||
processResult = _MockProcessResult();
|
||||
flutterValidator = _MockShorebirdFlutterValidator();
|
||||
shorebirdValidator = _MockShorebirdValidator();
|
||||
|
||||
registerFallbackValue(shorebirdProcess);
|
||||
|
||||
@@ -81,26 +87,44 @@ void main() {
|
||||
when(() => auth.client).thenReturn(httpClient);
|
||||
when(() => logger.progress(any())).thenReturn(_MockProgress());
|
||||
when(() => logger.info(any())).thenReturn(null);
|
||||
when(() => doctor.androidCommandValidators)
|
||||
.thenReturn([flutterValidator]);
|
||||
when(flutterValidator.validate).thenAnswer((_) async => []);
|
||||
when(
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: any(named: 'checkUserIsAuthenticated'),
|
||||
checkShorebirdInitialized: any(named: 'checkShorebirdInitialized'),
|
||||
validators: any(named: 'validators'),
|
||||
),
|
||||
).thenAnswer((_) async {});
|
||||
when(
|
||||
() => doctor.androidCommandValidators,
|
||||
).thenReturn([flutterValidator]);
|
||||
|
||||
command = runWithOverrides(BuildApkCommand.new)
|
||||
..testArgResults = argResults;
|
||||
});
|
||||
|
||||
test('has correct description', () {
|
||||
test('has a description', () {
|
||||
expect(command.description, isNotEmpty);
|
||||
});
|
||||
|
||||
test('exits with no user when not logged in', () async {
|
||||
when(() => auth.isAuthenticated).thenReturn(false);
|
||||
|
||||
final result = await runWithOverrides(command.run);
|
||||
expect(result, equals(ExitCode.noUser.code));
|
||||
|
||||
test('exits when validation fails', () async {
|
||||
final exception = ValidationFailedException();
|
||||
when(
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: any(named: 'checkUserIsAuthenticated'),
|
||||
checkShorebirdInitialized: any(named: 'checkShorebirdInitialized'),
|
||||
validators: any(named: 'validators'),
|
||||
),
|
||||
).thenThrow(exception);
|
||||
await expectLater(
|
||||
runWithOverrides(command.run),
|
||||
completion(equals(exception.exitCode.code)),
|
||||
);
|
||||
verify(
|
||||
() => logger.err(any(that: contains('You must be logged in to run'))),
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: true,
|
||||
checkShorebirdInitialized: true,
|
||||
validators: [flutterValidator],
|
||||
),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
@@ -187,58 +211,5 @@ ${lightCyan.wrap(p.join('build', 'app', 'outputs', 'apk', flavor, 'release', 'ap
|
||||
),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test('prints flutter validation warnings', () async {
|
||||
when(flutterValidator.validate).thenAnswer(
|
||||
(_) async => [
|
||||
const ValidationIssue(
|
||||
severity: ValidationIssueSeverity.warning,
|
||||
message: 'Flutter issue 1',
|
||||
),
|
||||
const ValidationIssue(
|
||||
severity: ValidationIssueSeverity.warning,
|
||||
message: 'Flutter issue 2',
|
||||
),
|
||||
],
|
||||
);
|
||||
when(() => processResult.exitCode).thenReturn(ExitCode.success.code);
|
||||
|
||||
final result = await runWithOverrides(command.run);
|
||||
|
||||
expect(result, equals(ExitCode.success.code));
|
||||
verify(
|
||||
() => logger.info(any(that: contains('Flutter issue 1'))),
|
||||
).called(1);
|
||||
verify(
|
||||
() => logger.info(any(that: contains('Flutter issue 2'))),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test('aborts if validation errors are present', () async {
|
||||
when(flutterValidator.validate).thenAnswer(
|
||||
(_) async => [
|
||||
ValidationIssue(
|
||||
severity: ValidationIssueSeverity.error,
|
||||
message: 'There was an issue',
|
||||
fix: () async {},
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
final result = await runWithOverrides(command.run);
|
||||
|
||||
expect(result, equals(ExitCode.config.code));
|
||||
verify(() => logger.err('Aborting due to validation errors.')).called(1);
|
||||
verify(
|
||||
() => logger.info(
|
||||
any(
|
||||
that: stringContainsInOrder([
|
||||
'issue can be fixed automatically',
|
||||
'shorebird doctor --fix',
|
||||
]),
|
||||
),
|
||||
),
|
||||
).called(1);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import 'package:shorebird_cli/src/commands/build/build.dart';
|
||||
import 'package:shorebird_cli/src/doctor.dart';
|
||||
import 'package:shorebird_cli/src/logger.dart';
|
||||
import 'package:shorebird_cli/src/process.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validator.dart';
|
||||
import 'package:shorebird_cli/src/validators/validators.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
@@ -33,6 +34,10 @@ class _MockShorebirdFlutterValidator extends Mock
|
||||
|
||||
class _MockShorebirdProcess extends Mock implements ShorebirdProcess {}
|
||||
|
||||
class _MockShorebirdValidator extends Mock implements ShorebirdValidator {}
|
||||
|
||||
class _FakeShorebirdProcess extends Fake implements ShorebirdProcess {}
|
||||
|
||||
void main() {
|
||||
group(BuildAppBundleCommand, () {
|
||||
late ArgResults argResults;
|
||||
@@ -44,6 +49,7 @@ void main() {
|
||||
late BuildAppBundleCommand command;
|
||||
late ShorebirdFlutterValidator flutterValidator;
|
||||
late ShorebirdProcess shorebirdProcess;
|
||||
late ShorebirdValidator shorebirdValidator;
|
||||
|
||||
R runWithOverrides<R>(R Function() body) {
|
||||
return runScoped(
|
||||
@@ -54,10 +60,15 @@ void main() {
|
||||
engineConfigRef.overrideWith(() => const EngineConfig.empty()),
|
||||
loggerRef.overrideWith(() => logger),
|
||||
processRef.overrideWith(() => shorebirdProcess),
|
||||
shorebirdValidatorRef.overrideWith(() => shorebirdValidator),
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
setUpAll(() {
|
||||
registerFallbackValue(_FakeShorebirdProcess());
|
||||
});
|
||||
|
||||
setUp(() {
|
||||
argResults = _MockArgResults();
|
||||
doctor = _MockDoctor();
|
||||
@@ -67,8 +78,7 @@ void main() {
|
||||
processResult = _MockProcessResult();
|
||||
flutterValidator = _MockShorebirdFlutterValidator();
|
||||
shorebirdProcess = _MockShorebirdProcess();
|
||||
|
||||
registerFallbackValue(shorebirdProcess);
|
||||
shorebirdValidator = _MockShorebirdValidator();
|
||||
|
||||
when(
|
||||
() => shorebirdProcess.run(
|
||||
@@ -82,26 +92,44 @@ void main() {
|
||||
when(() => auth.client).thenReturn(httpClient);
|
||||
when(() => logger.progress(any())).thenReturn(_MockProgress());
|
||||
when(() => logger.info(any())).thenReturn(null);
|
||||
when(flutterValidator.validate).thenAnswer((_) async => []);
|
||||
when(() => doctor.androidCommandValidators)
|
||||
.thenReturn([flutterValidator]);
|
||||
when(
|
||||
() => doctor.androidCommandValidators,
|
||||
).thenReturn([flutterValidator]);
|
||||
when(
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: any(named: 'checkUserIsAuthenticated'),
|
||||
checkShorebirdInitialized: any(named: 'checkShorebirdInitialized'),
|
||||
validators: any(named: 'validators'),
|
||||
),
|
||||
).thenAnswer((_) async {});
|
||||
|
||||
command = runWithOverrides(BuildAppBundleCommand.new)
|
||||
..testArgResults = argResults;
|
||||
});
|
||||
|
||||
test('has correct description', () {
|
||||
test('has a description', () {
|
||||
expect(command.description, isNotEmpty);
|
||||
});
|
||||
|
||||
test('exits with no user when not logged in', () async {
|
||||
when(() => auth.isAuthenticated).thenReturn(false);
|
||||
|
||||
final result = await runWithOverrides(command.run);
|
||||
expect(result, equals(ExitCode.noUser.code));
|
||||
|
||||
test('exits when validation fails', () async {
|
||||
final exception = ValidationFailedException();
|
||||
when(
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: any(named: 'checkUserIsAuthenticated'),
|
||||
checkShorebirdInitialized: any(named: 'checkShorebirdInitialized'),
|
||||
validators: any(named: 'validators'),
|
||||
),
|
||||
).thenThrow(exception);
|
||||
await expectLater(
|
||||
runWithOverrides(command.run),
|
||||
completion(equals(exception.exitCode.code)),
|
||||
);
|
||||
verify(
|
||||
() => logger.err(any(that: contains('You must be logged in to run'))),
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: true,
|
||||
checkShorebirdInitialized: true,
|
||||
validators: [flutterValidator],
|
||||
),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
@@ -226,47 +254,5 @@ ${lightCyan.wrap(p.join('build', 'app', 'outputs', 'bundle', '${flavor}Release',
|
||||
throwsException,
|
||||
);
|
||||
});
|
||||
|
||||
test('prints flutter validation warnings', () async {
|
||||
when(flutterValidator.validate).thenAnswer(
|
||||
(_) async => [
|
||||
const ValidationIssue(
|
||||
severity: ValidationIssueSeverity.warning,
|
||||
message: 'Flutter issue 1',
|
||||
),
|
||||
const ValidationIssue(
|
||||
severity: ValidationIssueSeverity.warning,
|
||||
message: 'Flutter issue 2',
|
||||
),
|
||||
],
|
||||
);
|
||||
when(() => processResult.exitCode).thenReturn(ExitCode.success.code);
|
||||
|
||||
final result = await runWithOverrides(command.run);
|
||||
|
||||
expect(result, equals(ExitCode.success.code));
|
||||
verify(
|
||||
() => logger.info(any(that: contains('Flutter issue 1'))),
|
||||
).called(1);
|
||||
verify(
|
||||
() => logger.info(any(that: contains('Flutter issue 2'))),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test('aborts if validation errors are present', () async {
|
||||
when(flutterValidator.validate).thenAnswer(
|
||||
(_) async => [
|
||||
const ValidationIssue(
|
||||
severity: ValidationIssueSeverity.error,
|
||||
message: 'There was an issue',
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
final result = await runWithOverrides(command.run);
|
||||
|
||||
expect(result, equals(ExitCode.config.code));
|
||||
verify(() => logger.err('Aborting due to validation errors.')).called(1);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import 'package:shorebird_cli/src/commands/build/build.dart';
|
||||
import 'package:shorebird_cli/src/doctor.dart';
|
||||
import 'package:shorebird_cli/src/logger.dart';
|
||||
import 'package:shorebird_cli/src/process.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validator.dart';
|
||||
import 'package:shorebird_cli/src/validators/validators.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
@@ -34,6 +35,10 @@ class _MockShorebirdFlutterValidator extends Mock
|
||||
|
||||
class _MockShorebirdProcess extends Mock implements ShorebirdProcess {}
|
||||
|
||||
class _MockShorebirdValidator extends Mock implements ShorebirdValidator {}
|
||||
|
||||
class _FakeShorebirdProcess extends Fake implements ShorebirdProcess {}
|
||||
|
||||
void main() {
|
||||
group(BuildIpaCommand, () {
|
||||
late ArgResults argResults;
|
||||
@@ -45,6 +50,7 @@ void main() {
|
||||
late BuildIpaCommand command;
|
||||
late ShorebirdFlutterValidator flutterValidator;
|
||||
late ShorebirdProcess shorebirdProcess;
|
||||
late ShorebirdValidator shorebirdValidator;
|
||||
|
||||
R runWithOverrides<R>(R Function() body) {
|
||||
return runScoped(
|
||||
@@ -54,10 +60,15 @@ void main() {
|
||||
doctorRef.overrideWith(() => doctor),
|
||||
loggerRef.overrideWith(() => logger),
|
||||
processRef.overrideWith(() => shorebirdProcess),
|
||||
shorebirdValidatorRef.overrideWith(() => shorebirdValidator),
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
setUpAll(() {
|
||||
registerFallbackValue(_FakeShorebirdProcess());
|
||||
});
|
||||
|
||||
setUp(() {
|
||||
argResults = _MockArgResults();
|
||||
httpClient = _MockHttpClient();
|
||||
@@ -67,8 +78,7 @@ void main() {
|
||||
shorebirdProcess = _MockShorebirdProcess();
|
||||
processResult = _MockProcessResult();
|
||||
flutterValidator = _MockShorebirdFlutterValidator();
|
||||
|
||||
registerFallbackValue(shorebirdProcess);
|
||||
shorebirdValidator = _MockShorebirdValidator();
|
||||
|
||||
when(
|
||||
() => shorebirdProcess.run(
|
||||
@@ -84,24 +94,41 @@ void main() {
|
||||
when(() => logger.progress(any())).thenReturn(_MockProgress());
|
||||
when(() => logger.info(any())).thenReturn(null);
|
||||
when(() => doctor.iosCommandValidators).thenReturn([flutterValidator]);
|
||||
when(flutterValidator.validate).thenAnswer((_) async => []);
|
||||
when(
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: any(named: 'checkUserIsAuthenticated'),
|
||||
checkShorebirdInitialized: any(named: 'checkShorebirdInitialized'),
|
||||
validators: any(named: 'validators'),
|
||||
),
|
||||
).thenAnswer((_) async {});
|
||||
|
||||
command = runWithOverrides(BuildIpaCommand.new)
|
||||
..testArgResults = argResults;
|
||||
});
|
||||
|
||||
test('has correct description', () {
|
||||
test('has a description', () {
|
||||
expect(command.description, isNotEmpty);
|
||||
});
|
||||
|
||||
test('exits with no user when not logged in', () async {
|
||||
when(() => auth.isAuthenticated).thenReturn(false);
|
||||
|
||||
final result = await runWithOverrides(command.run);
|
||||
expect(result, equals(ExitCode.noUser.code));
|
||||
|
||||
test('exits when validation fails', () async {
|
||||
final exception = ValidationFailedException();
|
||||
when(
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: any(named: 'checkUserIsAuthenticated'),
|
||||
checkShorebirdInitialized: any(named: 'checkShorebirdInitialized'),
|
||||
validators: any(named: 'validators'),
|
||||
),
|
||||
).thenThrow(exception);
|
||||
await expectLater(
|
||||
runWithOverrides(command.run),
|
||||
completion(equals(exception.exitCode.code)),
|
||||
);
|
||||
verify(
|
||||
() => logger.err(any(that: contains('You must be logged in to run'))),
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: true,
|
||||
checkShorebirdInitialized: true,
|
||||
validators: [flutterValidator],
|
||||
),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
@@ -253,59 +280,6 @@ ${lightCyan.wrap(p.join('build', 'ios', 'ipa', 'Runner.ipa'))}''',
|
||||
);
|
||||
});
|
||||
|
||||
test('prints flutter validation warnings', () async {
|
||||
when(flutterValidator.validate).thenAnswer(
|
||||
(_) async => [
|
||||
const ValidationIssue(
|
||||
severity: ValidationIssueSeverity.warning,
|
||||
message: 'Flutter issue 1',
|
||||
),
|
||||
const ValidationIssue(
|
||||
severity: ValidationIssueSeverity.warning,
|
||||
message: 'Flutter issue 2',
|
||||
),
|
||||
],
|
||||
);
|
||||
when(() => processResult.exitCode).thenReturn(ExitCode.success.code);
|
||||
|
||||
final result = await runWithOverrides(command.run);
|
||||
|
||||
expect(result, equals(ExitCode.success.code));
|
||||
verify(
|
||||
() => logger.info(any(that: contains('Flutter issue 1'))),
|
||||
).called(1);
|
||||
verify(
|
||||
() => logger.info(any(that: contains('Flutter issue 2'))),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test('aborts if validation errors are present', () async {
|
||||
when(flutterValidator.validate).thenAnswer(
|
||||
(_) async => [
|
||||
ValidationIssue(
|
||||
severity: ValidationIssueSeverity.error,
|
||||
message: 'There was an issue',
|
||||
fix: () async {},
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
final result = await runWithOverrides(command.run);
|
||||
|
||||
expect(result, equals(ExitCode.config.code));
|
||||
verify(() => logger.err('Aborting due to validation errors.')).called(1);
|
||||
verify(
|
||||
() => logger.info(
|
||||
any(
|
||||
that: stringContainsInOrder([
|
||||
'issue can be fixed automatically',
|
||||
'shorebird doctor --fix',
|
||||
]),
|
||||
),
|
||||
),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test('provides appropriate ExportOptions.plist to build ipa command',
|
||||
() async {
|
||||
when(() => processResult.exitCode).thenReturn(ExitCode.success.code);
|
||||
|
||||
+28
-4
@@ -6,6 +6,7 @@ import 'package:scoped/scoped.dart';
|
||||
import 'package:shorebird_cli/src/auth/auth.dart';
|
||||
import 'package:shorebird_cli/src/commands/commands.dart';
|
||||
import 'package:shorebird_cli/src/logger.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validator.dart';
|
||||
import 'package:shorebird_code_push_client/shorebird_code_push_client.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
@@ -21,6 +22,8 @@ class _MockLogger extends Mock implements Logger {}
|
||||
|
||||
class _MockProgress extends Mock implements Progress {}
|
||||
|
||||
class _MockShorebirdValidator extends Mock implements ShorebirdValidator {}
|
||||
|
||||
void main() {
|
||||
group(AddCollaboratorsCommand, () {
|
||||
const appId = 'test-app-id';
|
||||
@@ -32,6 +35,7 @@ void main() {
|
||||
late CodePushClient codePushClient;
|
||||
late Logger logger;
|
||||
late Progress progress;
|
||||
late ShorebirdValidator shorebirdValidator;
|
||||
late AddCollaboratorsCommand command;
|
||||
|
||||
R runWithOverrides<R>(R Function() body) {
|
||||
@@ -39,7 +43,8 @@ void main() {
|
||||
body,
|
||||
values: {
|
||||
authRef.overrideWith(() => auth),
|
||||
loggerRef.overrideWith(() => logger)
|
||||
loggerRef.overrideWith(() => logger),
|
||||
shorebirdValidatorRef.overrideWith(() => shorebirdValidator),
|
||||
},
|
||||
);
|
||||
}
|
||||
@@ -51,6 +56,7 @@ void main() {
|
||||
codePushClient = _MockCodePushClient();
|
||||
logger = _MockLogger();
|
||||
progress = _MockProgress();
|
||||
shorebirdValidator = _MockShorebirdValidator();
|
||||
|
||||
when(() => argResults['app-id']).thenReturn(appId);
|
||||
when(() => argResults['email']).thenReturn(email);
|
||||
@@ -58,6 +64,11 @@ void main() {
|
||||
when(() => auth.isAuthenticated).thenReturn(true);
|
||||
when(() => logger.confirm(any())).thenReturn(true);
|
||||
when(() => logger.progress(any())).thenReturn(progress);
|
||||
when(
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: any(named: 'checkUserIsAuthenticated'),
|
||||
),
|
||||
).thenAnswer((_) async {});
|
||||
|
||||
command = runWithOverrides(
|
||||
() => AddCollaboratorsCommand(
|
||||
@@ -82,9 +93,22 @@ void main() {
|
||||
);
|
||||
});
|
||||
|
||||
test('returns ExitCode.noUser when not logged in', () async {
|
||||
when(() => auth.isAuthenticated).thenReturn(false);
|
||||
expect(await runWithOverrides(command.run), ExitCode.noUser.code);
|
||||
test('exits when validation fails', () async {
|
||||
final exception = ValidationFailedException();
|
||||
when(
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: any(named: 'checkUserIsAuthenticated'),
|
||||
),
|
||||
).thenThrow(exception);
|
||||
await expectLater(
|
||||
runWithOverrides(command.run),
|
||||
completion(equals(exception.exitCode.code)),
|
||||
);
|
||||
verify(
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: true,
|
||||
),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test('returns ExitCode.usage when app id is missing.', () async {
|
||||
|
||||
+28
-4
@@ -9,6 +9,7 @@ import 'package:scoped/scoped.dart';
|
||||
import 'package:shorebird_cli/src/auth/auth.dart';
|
||||
import 'package:shorebird_cli/src/commands/commands.dart';
|
||||
import 'package:shorebird_cli/src/logger.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validator.dart';
|
||||
import 'package:shorebird_code_push_client/shorebird_code_push_client.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
@@ -24,6 +25,8 @@ class _MockLogger extends Mock implements Logger {}
|
||||
|
||||
class _MockProgress extends Mock implements Progress {}
|
||||
|
||||
class _MockShorebirdValidator extends Mock implements ShorebirdValidator {}
|
||||
|
||||
void main() {
|
||||
group(DeleteCollaboratorsCommand, () {
|
||||
const appId = 'test-app-id';
|
||||
@@ -40,6 +43,7 @@ void main() {
|
||||
late CodePushClient codePushClient;
|
||||
late Logger logger;
|
||||
late Progress progress;
|
||||
late ShorebirdValidator shorebirdValidator;
|
||||
late DeleteCollaboratorsCommand command;
|
||||
|
||||
R runWithOverrides<R>(R Function() body) {
|
||||
@@ -47,7 +51,8 @@ void main() {
|
||||
body,
|
||||
values: {
|
||||
authRef.overrideWith(() => auth),
|
||||
loggerRef.overrideWith(() => logger)
|
||||
loggerRef.overrideWith(() => logger),
|
||||
shorebirdValidatorRef.overrideWith(() => shorebirdValidator),
|
||||
},
|
||||
);
|
||||
}
|
||||
@@ -59,6 +64,7 @@ void main() {
|
||||
codePushClient = _MockCodePushClient();
|
||||
logger = _MockLogger();
|
||||
progress = _MockProgress();
|
||||
shorebirdValidator = _MockShorebirdValidator();
|
||||
|
||||
when(() => argResults['app-id']).thenReturn(appId);
|
||||
when(() => argResults['email']).thenReturn(email);
|
||||
@@ -75,6 +81,11 @@ void main() {
|
||||
userId: any(named: 'userId'),
|
||||
),
|
||||
).thenAnswer((_) async {});
|
||||
when(
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: any(named: 'checkUserIsAuthenticated'),
|
||||
),
|
||||
).thenAnswer((_) async {});
|
||||
|
||||
command = runWithOverrides(
|
||||
() => DeleteCollaboratorsCommand(
|
||||
@@ -95,9 +106,22 @@ void main() {
|
||||
);
|
||||
});
|
||||
|
||||
test('returns ExitCode.noUser when not logged in', () async {
|
||||
when(() => auth.isAuthenticated).thenReturn(false);
|
||||
expect(await runWithOverrides(command.run), ExitCode.noUser.code);
|
||||
test('exits when validation fails', () async {
|
||||
final exception = ValidationFailedException();
|
||||
when(
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: any(named: 'checkUserIsAuthenticated'),
|
||||
),
|
||||
).thenThrow(exception);
|
||||
await expectLater(
|
||||
runWithOverrides(command.run),
|
||||
completion(equals(exception.exitCode.code)),
|
||||
);
|
||||
verify(
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: true,
|
||||
),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test('returns ExitCode.usage when app id is missing.', () async {
|
||||
|
||||
+28
-4
@@ -6,6 +6,7 @@ import 'package:scoped/scoped.dart';
|
||||
import 'package:shorebird_cli/src/auth/auth.dart';
|
||||
import 'package:shorebird_cli/src/commands/commands.dart';
|
||||
import 'package:shorebird_cli/src/logger.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validator.dart';
|
||||
import 'package:shorebird_code_push_client/shorebird_code_push_client.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
@@ -19,6 +20,8 @@ class _MockCodePushClient extends Mock implements CodePushClient {}
|
||||
|
||||
class _MockLogger extends Mock implements Logger {}
|
||||
|
||||
class _MockShorebirdValidator extends Mock implements ShorebirdValidator {}
|
||||
|
||||
void main() {
|
||||
group(ListCollaboratorsCommand, () {
|
||||
const appId = 'test-app-id';
|
||||
@@ -28,6 +31,7 @@ void main() {
|
||||
late Auth auth;
|
||||
late CodePushClient codePushClient;
|
||||
late Logger logger;
|
||||
late ShorebirdValidator shorebirdValidator;
|
||||
late ListCollaboratorsCommand command;
|
||||
|
||||
R runWithOverrides<R>(R Function() body) {
|
||||
@@ -35,7 +39,8 @@ void main() {
|
||||
body,
|
||||
values: {
|
||||
authRef.overrideWith(() => auth),
|
||||
loggerRef.overrideWith(() => logger)
|
||||
loggerRef.overrideWith(() => logger),
|
||||
shorebirdValidatorRef.overrideWith(() => shorebirdValidator),
|
||||
},
|
||||
);
|
||||
}
|
||||
@@ -46,10 +51,16 @@ void main() {
|
||||
auth = _MockAuth();
|
||||
codePushClient = _MockCodePushClient();
|
||||
logger = _MockLogger();
|
||||
shorebirdValidator = _MockShorebirdValidator();
|
||||
|
||||
when(() => argResults['app-id']).thenReturn(appId);
|
||||
when(() => auth.client).thenReturn(httpClient);
|
||||
when(() => auth.isAuthenticated).thenReturn(true);
|
||||
when(
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: any(named: 'checkUserIsAuthenticated'),
|
||||
),
|
||||
).thenAnswer((_) async {});
|
||||
|
||||
command = runWithOverrides(
|
||||
() => ListCollaboratorsCommand(
|
||||
@@ -78,9 +89,22 @@ void main() {
|
||||
expect(command.aliases, equals(['ls']));
|
||||
});
|
||||
|
||||
test('returns ExitCode.noUser when not logged in', () async {
|
||||
when(() => auth.isAuthenticated).thenReturn(false);
|
||||
expect(await runWithOverrides(command.run), ExitCode.noUser.code);
|
||||
test('exits when validation fails', () async {
|
||||
final exception = ValidationFailedException();
|
||||
when(
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: any(named: 'checkUserIsAuthenticated'),
|
||||
),
|
||||
).thenThrow(exception);
|
||||
await expectLater(
|
||||
runWithOverrides(command.run),
|
||||
completion(equals(exception.exitCode.code)),
|
||||
);
|
||||
verify(
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: true,
|
||||
),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test('returns ExitCode.usage when app id is missing.', () async {
|
||||
|
||||
@@ -14,6 +14,7 @@ import 'package:shorebird_cli/src/gradlew.dart';
|
||||
import 'package:shorebird_cli/src/logger.dart';
|
||||
import 'package:shorebird_cli/src/platform.dart';
|
||||
import 'package:shorebird_cli/src/process.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validator.dart';
|
||||
import 'package:shorebird_cli/src/xcodebuild.dart';
|
||||
import 'package:shorebird_code_push_client/shorebird_code_push_client.dart';
|
||||
import 'package:test/test.dart';
|
||||
@@ -36,6 +37,8 @@ class _MockPlatform extends Mock implements Platform {}
|
||||
|
||||
class _MockProgress extends Mock implements Progress {}
|
||||
|
||||
class _MockShorebirdValidator extends Mock implements ShorebirdValidator {}
|
||||
|
||||
class _MockXcodeBuild extends Mock implements XcodeBuild {}
|
||||
|
||||
void main() {
|
||||
@@ -60,6 +63,7 @@ environment:
|
||||
late Logger logger;
|
||||
late Platform platform;
|
||||
late Progress progress;
|
||||
late ShorebirdValidator shorebirdValidator;
|
||||
late XcodeBuild xcodeBuild;
|
||||
late InitCommand command;
|
||||
|
||||
@@ -73,6 +77,7 @@ environment:
|
||||
loggerRef.overrideWith(() => logger),
|
||||
platformRef.overrideWith(() => platform),
|
||||
processRef.overrideWith(() => process),
|
||||
shorebirdValidatorRef.overrideWith(() => shorebirdValidator),
|
||||
xcodeBuildRef.overrideWith(() => xcodeBuild),
|
||||
},
|
||||
);
|
||||
@@ -95,6 +100,7 @@ environment:
|
||||
logger = _MockLogger();
|
||||
platform = _MockPlatform();
|
||||
progress = _MockProgress();
|
||||
shorebirdValidator = _MockShorebirdValidator();
|
||||
xcodeBuild = _MockXcodeBuild();
|
||||
|
||||
when(() => auth.isAuthenticated).thenReturn(true);
|
||||
@@ -115,6 +121,11 @@ environment:
|
||||
when(() => logger.progress(any())).thenReturn(progress);
|
||||
when(() => gradlew.productFlavors(any())).thenAnswer((_) async => {});
|
||||
when(() => platform.isMacOS).thenReturn(true);
|
||||
when(
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: any(named: 'checkUserIsAuthenticated'),
|
||||
),
|
||||
).thenAnswer((_) async {});
|
||||
when(
|
||||
() => xcodeBuild.list(any()),
|
||||
).thenAnswer((_) async => const XcodeProjectBuildInfo());
|
||||
@@ -131,10 +142,22 @@ environment:
|
||||
)..testArgResults = argResults;
|
||||
});
|
||||
|
||||
test('returns no user error when not logged in', () async {
|
||||
when(() => auth.isAuthenticated).thenReturn(false);
|
||||
final result = await runWithOverrides(command.run);
|
||||
expect(result, ExitCode.noUser.code);
|
||||
test('exits when validation fails', () async {
|
||||
final exception = ValidationFailedException();
|
||||
when(
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: any(named: 'checkUserIsAuthenticated'),
|
||||
),
|
||||
).thenThrow(exception);
|
||||
await expectLater(
|
||||
runWithOverrides(command.run),
|
||||
completion(equals(exception.exitCode.code)),
|
||||
);
|
||||
verify(
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: true,
|
||||
),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test('throws no input error when pubspec.yaml is not found.', () async {
|
||||
|
||||
@@ -17,6 +17,7 @@ import 'package:shorebird_cli/src/platform.dart';
|
||||
import 'package:shorebird_cli/src/process.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_build_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_environment.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validator.dart';
|
||||
import 'package:shorebird_code_push_client/shorebird_code_push_client.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
@@ -45,6 +46,8 @@ class _MockHttpClient extends Mock implements http.Client {}
|
||||
|
||||
class _MockShorebirdProcess extends Mock implements ShorebirdProcess {}
|
||||
|
||||
class _MockShorebirdValidator extends Mock implements ShorebirdValidator {}
|
||||
|
||||
class _FakeShorebirdProcess extends Fake implements ShorebirdProcess {}
|
||||
|
||||
void main() {
|
||||
@@ -123,8 +126,9 @@ flutter:
|
||||
late ShorebirdProcessResult patchProcessResult;
|
||||
late http.Client httpClient;
|
||||
late Cache cache;
|
||||
late PatchAarCommand command;
|
||||
late ShorebirdProcess shorebirdProcess;
|
||||
late ShorebirdValidator shorebirdValidator;
|
||||
late PatchAarCommand command;
|
||||
|
||||
R runWithOverrides<R>(R Function() body) {
|
||||
return runScoped(
|
||||
@@ -137,6 +141,7 @@ flutter:
|
||||
loggerRef.overrideWith(() => logger),
|
||||
platformRef.overrideWith(() => platform),
|
||||
processRef.overrideWith(() => shorebirdProcess),
|
||||
shorebirdValidatorRef.overrideWith(() => shorebirdValidator),
|
||||
},
|
||||
);
|
||||
}
|
||||
@@ -203,6 +208,7 @@ flutter:
|
||||
httpClient = _MockHttpClient();
|
||||
cache = _MockCache();
|
||||
shorebirdProcess = _MockShorebirdProcess();
|
||||
shorebirdValidator = _MockShorebirdValidator();
|
||||
|
||||
registerFallbackValue(ReleasePlatform.android);
|
||||
|
||||
@@ -323,6 +329,12 @@ flutter:
|
||||
when(
|
||||
() => cache.getArtifactDirectory(any()),
|
||||
).thenReturn(Directory.systemTemp.createTempSync());
|
||||
when(
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: any(named: 'checkUserIsAuthenticated'),
|
||||
checkShorebirdInitialized: any(named: 'checkShorebirdInitialized'),
|
||||
),
|
||||
).thenAnswer((_) async {});
|
||||
|
||||
command = runWithOverrides(
|
||||
() => PatchAarCommand(
|
||||
@@ -333,32 +345,28 @@ flutter:
|
||||
)..testArgResults = argResults;
|
||||
});
|
||||
|
||||
test('throws config error when shorebird is not initialized', () async {
|
||||
final tempDir = Directory.systemTemp.createTempSync();
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
verify(
|
||||
() => logger.err(
|
||||
'Shorebird is not initialized. Did you run "shorebird init"?',
|
||||
),
|
||||
).called(1);
|
||||
expect(exitCode, ExitCode.config.code);
|
||||
});
|
||||
|
||||
test('has a description', () {
|
||||
expect(command.description, isNotEmpty);
|
||||
});
|
||||
|
||||
test('throws no user error when user is not logged in', () async {
|
||||
when(() => auth.isAuthenticated).thenReturn(false);
|
||||
final tempDir = setUpTempDir();
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
test('exits when validation fails', () async {
|
||||
final exception = ValidationFailedException();
|
||||
when(
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: any(named: 'checkUserIsAuthenticated'),
|
||||
checkShorebirdInitialized: any(named: 'checkShorebirdInitialized'),
|
||||
),
|
||||
).thenThrow(exception);
|
||||
await expectLater(
|
||||
runWithOverrides(command.run),
|
||||
completion(equals(exception.exitCode.code)),
|
||||
);
|
||||
expect(exitCode, equals(ExitCode.noUser.code));
|
||||
verify(
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: true,
|
||||
checkShorebirdInitialized: true,
|
||||
),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test('exits with 78 if no module entry exists in pubspec.yaml', () async {
|
||||
|
||||
@@ -21,6 +21,7 @@ import 'package:shorebird_cli/src/platform.dart';
|
||||
import 'package:shorebird_cli/src/process.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_build_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_environment.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validator.dart';
|
||||
import 'package:shorebird_cli/src/validators/validators.dart';
|
||||
import 'package:shorebird_code_push_client/shorebird_code_push_client.dart';
|
||||
import 'package:test/test.dart';
|
||||
@@ -59,6 +60,8 @@ class _MockShorebirdFlutterValidator extends Mock
|
||||
|
||||
class _MockShorebirdProcess extends Mock implements ShorebirdProcess {}
|
||||
|
||||
class _MockShorebirdValidator extends Mock implements ShorebirdValidator {}
|
||||
|
||||
class _FakeShorebirdProcess extends Fake implements ShorebirdProcess {}
|
||||
|
||||
void main() {
|
||||
@@ -125,9 +128,10 @@ flutter:
|
||||
late ShorebirdProcessResult patchProcessResult;
|
||||
late http.Client httpClient;
|
||||
late Cache cache;
|
||||
late PatchAndroidCommand command;
|
||||
late ShorebirdFlutterValidator flutterValidator;
|
||||
late ShorebirdProcess shorebirdProcess;
|
||||
late ShorebirdValidator shorebirdValidator;
|
||||
late PatchAndroidCommand command;
|
||||
|
||||
R runWithOverrides<R>(R Function() body) {
|
||||
return runScoped(
|
||||
@@ -143,6 +147,7 @@ flutter:
|
||||
loggerRef.overrideWith(() => logger),
|
||||
platformRef.overrideWith(() => platform),
|
||||
processRef.overrideWith(() => shorebirdProcess),
|
||||
shorebirdValidatorRef.overrideWith(() => shorebirdValidator),
|
||||
},
|
||||
);
|
||||
}
|
||||
@@ -203,6 +208,7 @@ flutter:
|
||||
flutterValidator = _MockShorebirdFlutterValidator();
|
||||
cache = _MockCache();
|
||||
shorebirdProcess = _MockShorebirdProcess();
|
||||
shorebirdValidator = _MockShorebirdValidator();
|
||||
command = runWithOverrides(
|
||||
() => PatchAndroidCommand(
|
||||
aabDiffer: aabDiffer,
|
||||
@@ -341,34 +347,39 @@ flutter:
|
||||
when(() => bundletool.getVersionCode(any())).thenAnswer(
|
||||
(_) async => versionCode,
|
||||
);
|
||||
});
|
||||
|
||||
test('throws config error when shorebird is not initialized', () async {
|
||||
final tempDir = Directory.systemTemp.createTempSync();
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
verify(
|
||||
() => logger.err(
|
||||
'Shorebird is not initialized. Did you run "shorebird init"?',
|
||||
when(
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: any(named: 'checkUserIsAuthenticated'),
|
||||
checkShorebirdInitialized: any(named: 'checkShorebirdInitialized'),
|
||||
validators: any(named: 'validators'),
|
||||
),
|
||||
).called(1);
|
||||
expect(exitCode, ExitCode.config.code);
|
||||
).thenAnswer((_) async {});
|
||||
});
|
||||
|
||||
test('has a description', () {
|
||||
expect(command.description, isNotEmpty);
|
||||
});
|
||||
|
||||
test('throws no user error when user is not logged in', () async {
|
||||
when(() => auth.isAuthenticated).thenReturn(false);
|
||||
final tempDir = setUpTempDir();
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
test('exits when validation fails', () async {
|
||||
final exception = ValidationFailedException();
|
||||
when(
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: any(named: 'checkUserIsAuthenticated'),
|
||||
checkShorebirdInitialized: any(named: 'checkShorebirdInitialized'),
|
||||
validators: any(named: 'validators'),
|
||||
),
|
||||
).thenThrow(exception);
|
||||
await expectLater(
|
||||
runWithOverrides(command.run),
|
||||
completion(equals(exception.exitCode.code)),
|
||||
);
|
||||
expect(exitCode, equals(ExitCode.noUser.code));
|
||||
verify(
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: true,
|
||||
checkShorebirdInitialized: true,
|
||||
validators: [flutterValidator],
|
||||
),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test('exits with code 70 when building fails', () async {
|
||||
@@ -860,56 +871,5 @@ flavors:
|
||||
verify(() => logger.success('\n✅ Published Patch!')).called(1);
|
||||
expect(exitCode, ExitCode.success.code);
|
||||
});
|
||||
|
||||
test('prints flutter validation warnings', () async {
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
when(flutterValidator.validate).thenAnswer(
|
||||
(_) async => [
|
||||
const ValidationIssue(
|
||||
severity: ValidationIssueSeverity.warning,
|
||||
message: 'Flutter issue 1',
|
||||
),
|
||||
const ValidationIssue(
|
||||
severity: ValidationIssueSeverity.warning,
|
||||
message: 'Flutter issue 2',
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
|
||||
expect(exitCode, equals(ExitCode.success.code));
|
||||
verify(
|
||||
() => logger.info(any(that: contains('Flutter issue 1'))),
|
||||
).called(1);
|
||||
verify(
|
||||
() => logger.info(any(that: contains('Flutter issue 2'))),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test('aborts if validation errors are present', () async {
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
when(flutterValidator.validate).thenAnswer(
|
||||
(_) async => [
|
||||
const ValidationIssue(
|
||||
severity: ValidationIssueSeverity.error,
|
||||
message: 'There was an issue',
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
|
||||
expect(exitCode, equals(ExitCode.config.code));
|
||||
verify(() => logger.err('Aborting due to validation errors.')).called(1);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ import 'package:shorebird_cli/src/logger.dart';
|
||||
import 'package:shorebird_cli/src/platform.dart';
|
||||
import 'package:shorebird_cli/src/process.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_environment.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validator.dart';
|
||||
import 'package:shorebird_cli/src/third_party/flutter_tools/lib/flutter_tools.dart';
|
||||
import 'package:shorebird_cli/src/validators/validators.dart';
|
||||
import 'package:shorebird_code_push_client/shorebird_code_push_client.dart';
|
||||
@@ -52,6 +53,8 @@ class _MockShorebirdFlutterValidator extends Mock
|
||||
|
||||
class _MockShorebirdProcess extends Mock implements ShorebirdProcess {}
|
||||
|
||||
class _MockShorebirdValidator extends Mock implements ShorebirdValidator {}
|
||||
|
||||
class _FakeShorebirdProcess extends Fake implements ShorebirdProcess {}
|
||||
|
||||
void main() {
|
||||
@@ -109,6 +112,7 @@ flutter:
|
||||
late http.Client httpClient;
|
||||
late ShorebirdFlutterValidator flutterValidator;
|
||||
late ShorebirdProcess shorebirdProcess;
|
||||
late ShorebirdValidator shorebirdValidator;
|
||||
late PatchIosCommand command;
|
||||
|
||||
R runWithOverrides<R>(R Function() body) {
|
||||
@@ -121,6 +125,7 @@ flutter:
|
||||
loggerRef.overrideWith(() => logger),
|
||||
platformRef.overrideWith(() => platform),
|
||||
processRef.overrideWith(() => shorebirdProcess),
|
||||
shorebirdValidatorRef.overrideWith(() => shorebirdValidator),
|
||||
},
|
||||
);
|
||||
}
|
||||
@@ -182,6 +187,7 @@ flutter:
|
||||
httpClient = _MockHttpClient();
|
||||
flutterValidator = _MockShorebirdFlutterValidator();
|
||||
shorebirdProcess = _MockShorebirdProcess();
|
||||
shorebirdValidator = _MockShorebirdValidator();
|
||||
|
||||
when(() => argResults['arch']).thenReturn(arch);
|
||||
when(() => argResults['dry-run']).thenReturn(false);
|
||||
@@ -256,6 +262,14 @@ flutter:
|
||||
runInShell: any(named: 'runInShell'),
|
||||
),
|
||||
).thenAnswer((_) async => aotBuildProcessResult);
|
||||
when(
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: any(named: 'checkUserIsAuthenticated'),
|
||||
checkShorebirdInitialized: any(named: 'checkShorebirdInitialized'),
|
||||
validators: any(named: 'validators'),
|
||||
supportedOperatingSystems: any(named: 'supportedOperatingSystems'),
|
||||
),
|
||||
).thenAnswer((_) async {});
|
||||
|
||||
command = runWithOverrides(() => PatchIosCommand(ipaReader: ipaReader))
|
||||
..testArgResults = argResults;
|
||||
@@ -265,24 +279,28 @@ flutter:
|
||||
expect(command.description, isNotEmpty);
|
||||
});
|
||||
|
||||
test('exits with unavailable code if run on non-macOS platform', () async {
|
||||
when(() => platform.operatingSystem).thenReturn(Platform.windows);
|
||||
|
||||
final result = await runWithOverrides(command.run);
|
||||
|
||||
expect(result, equals(ExitCode.unavailable.code));
|
||||
verify(() => logger.err('This command is only supported on macos.'))
|
||||
.called(1);
|
||||
});
|
||||
|
||||
test('throws no user error when user is not logged in', () async {
|
||||
when(() => auth.isAuthenticated).thenReturn(false);
|
||||
final tempDir = setUpTempDir();
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
test('exits when validation fails', () async {
|
||||
final exception = ValidationFailedException();
|
||||
when(
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: any(named: 'checkUserIsAuthenticated'),
|
||||
checkShorebirdInitialized: any(named: 'checkShorebirdInitialized'),
|
||||
validators: any(named: 'validators'),
|
||||
supportedOperatingSystems: any(named: 'supportedOperatingSystems'),
|
||||
),
|
||||
).thenThrow(exception);
|
||||
await expectLater(
|
||||
runWithOverrides(command.run),
|
||||
completion(equals(exception.exitCode.code)),
|
||||
);
|
||||
expect(exitCode, equals(ExitCode.noUser.code));
|
||||
verify(
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: true,
|
||||
checkShorebirdInitialized: true,
|
||||
validators: [flutterValidator],
|
||||
supportedOperatingSystems: {Platform.macOS},
|
||||
),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test('exits with code 70 when building fails', () async {
|
||||
@@ -625,56 +643,5 @@ base_url: $baseUrl''',
|
||||
expect(exportOptionsPlist['uploadBitcode'], isFalse);
|
||||
expect(exportOptionsPlist['method'], 'app-store');
|
||||
});
|
||||
|
||||
test('prints flutter validation warnings', () async {
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
when(flutterValidator.validate).thenAnswer(
|
||||
(_) async => [
|
||||
const ValidationIssue(
|
||||
severity: ValidationIssueSeverity.warning,
|
||||
message: 'Flutter issue 1',
|
||||
),
|
||||
const ValidationIssue(
|
||||
severity: ValidationIssueSeverity.warning,
|
||||
message: 'Flutter issue 2',
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
|
||||
expect(exitCode, equals(ExitCode.success.code));
|
||||
verify(
|
||||
() => logger.info(any(that: contains('Flutter issue 1'))),
|
||||
).called(1);
|
||||
verify(
|
||||
() => logger.info(any(that: contains('Flutter issue 2'))),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test('aborts if validation errors are present', () async {
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
when(flutterValidator.validate).thenAnswer(
|
||||
(_) async => [
|
||||
const ValidationIssue(
|
||||
severity: ValidationIssueSeverity.error,
|
||||
message: 'There was an issue',
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
|
||||
expect(exitCode, equals(ExitCode.config.code));
|
||||
verify(() => logger.err('Aborting due to validation errors.')).called(1);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
+33
-80
@@ -14,6 +14,7 @@ import 'package:shorebird_cli/src/logger.dart';
|
||||
import 'package:shorebird_cli/src/platform.dart';
|
||||
import 'package:shorebird_cli/src/process.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_environment.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validator.dart';
|
||||
import 'package:shorebird_cli/src/validators/validators.dart';
|
||||
import 'package:shorebird_code_push_client/shorebird_code_push_client.dart';
|
||||
import 'package:test/test.dart';
|
||||
@@ -40,6 +41,8 @@ class _MockShorebirdFlutterValidator extends Mock
|
||||
|
||||
class _MockShorebirdProcess extends Mock implements ShorebirdProcess {}
|
||||
|
||||
class _MockShorebirdValidator extends Mock implements ShorebirdValidator {}
|
||||
|
||||
void main() {
|
||||
group(PatchIosFrameworkCommand, () {
|
||||
const appDisplayName = 'Test App';
|
||||
@@ -79,9 +82,10 @@ flutter:
|
||||
late ShorebirdProcessResult aotBuildProcessResult;
|
||||
late ShorebirdProcessResult flutterBuildProcessResult;
|
||||
late ShorebirdProcessResult flutterRevisionProcessResult;
|
||||
late PatchIosFrameworkCommand command;
|
||||
late ShorebirdFlutterValidator flutterValidator;
|
||||
late ShorebirdProcess shorebirdProcess;
|
||||
late ShorebirdValidator shorebirdValidator;
|
||||
late PatchIosFrameworkCommand command;
|
||||
|
||||
R runWithOverrides<R>(R Function() body) {
|
||||
return runScoped(
|
||||
@@ -93,6 +97,7 @@ flutter:
|
||||
loggerRef.overrideWith(() => logger),
|
||||
platformRef.overrideWith(() => platform),
|
||||
processRef.overrideWith(() => shorebirdProcess),
|
||||
shorebirdValidatorRef.overrideWith(() => shorebirdValidator),
|
||||
},
|
||||
);
|
||||
}
|
||||
@@ -145,6 +150,7 @@ flutter:
|
||||
flutterRevisionProcessResult = _MockProcessResult();
|
||||
flutterValidator = _MockShorebirdFlutterValidator();
|
||||
shorebirdProcess = _MockShorebirdProcess();
|
||||
shorebirdValidator = _MockShorebirdValidator();
|
||||
|
||||
when(
|
||||
() => shorebirdProcess.run(
|
||||
@@ -214,6 +220,14 @@ flutter:
|
||||
patchArtifactBundles: any(named: 'patchArtifactBundles'),
|
||||
),
|
||||
).thenAnswer((_) async {});
|
||||
when(
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: any(named: 'checkUserIsAuthenticated'),
|
||||
checkShorebirdInitialized: any(named: 'checkShorebirdInitialized'),
|
||||
validators: any(named: 'validators'),
|
||||
supportedOperatingSystems: any(named: 'supportedOperatingSystems'),
|
||||
),
|
||||
).thenAnswer((_) async {});
|
||||
|
||||
command = runWithOverrides(PatchIosFrameworkCommand.new)
|
||||
..testArgResults = argResults;
|
||||
@@ -223,38 +237,28 @@ flutter:
|
||||
expect(command.description, isNotEmpty);
|
||||
});
|
||||
|
||||
test('exits with unavailable code if run on non-macOS platform', () async {
|
||||
when(() => platform.operatingSystem).thenReturn(Platform.windows);
|
||||
|
||||
final result = await runWithOverrides(command.run);
|
||||
|
||||
expect(result, equals(ExitCode.unavailable.code));
|
||||
verify(() => logger.err('This command is only supported on macos.'))
|
||||
.called(1);
|
||||
});
|
||||
|
||||
test('throws config error when shorebird is not initialized', () async {
|
||||
final tempDir = Directory.systemTemp.createTempSync();
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
test('exits when validation fails', () async {
|
||||
final exception = ValidationFailedException();
|
||||
when(
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: any(named: 'checkUserIsAuthenticated'),
|
||||
checkShorebirdInitialized: any(named: 'checkShorebirdInitialized'),
|
||||
validators: any(named: 'validators'),
|
||||
supportedOperatingSystems: any(named: 'supportedOperatingSystems'),
|
||||
),
|
||||
).thenThrow(exception);
|
||||
await expectLater(
|
||||
runWithOverrides(command.run),
|
||||
completion(equals(exception.exitCode.code)),
|
||||
);
|
||||
verify(
|
||||
() => logger.err(
|
||||
'Shorebird is not initialized. Did you run "shorebird init"?',
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: true,
|
||||
checkShorebirdInitialized: true,
|
||||
validators: [flutterValidator],
|
||||
supportedOperatingSystems: {Platform.macOS},
|
||||
),
|
||||
).called(1);
|
||||
expect(exitCode, ExitCode.config.code);
|
||||
});
|
||||
|
||||
test('throws no user error when user is not logged in', () async {
|
||||
when(() => auth.isAuthenticated).thenReturn(false);
|
||||
final tempDir = setUpTempDir();
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
expect(exitCode, equals(ExitCode.noUser.code));
|
||||
});
|
||||
|
||||
test('aborts when user opts out', () async {
|
||||
@@ -477,56 +481,5 @@ https://github.com/shorebirdtech/shorebird/issues/472
|
||||
verify(() => logger.success('\n✅ Published Patch!')).called(1);
|
||||
expect(exitCode, ExitCode.success.code);
|
||||
});
|
||||
|
||||
test('prints flutter validation warnings', () async {
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
when(flutterValidator.validate).thenAnswer(
|
||||
(_) async => [
|
||||
const ValidationIssue(
|
||||
severity: ValidationIssueSeverity.warning,
|
||||
message: 'Flutter issue 1',
|
||||
),
|
||||
const ValidationIssue(
|
||||
severity: ValidationIssueSeverity.warning,
|
||||
message: 'Flutter issue 2',
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
|
||||
expect(exitCode, equals(ExitCode.success.code));
|
||||
verify(
|
||||
() => logger.info(any(that: contains('Flutter issue 1'))),
|
||||
).called(1);
|
||||
verify(
|
||||
() => logger.info(any(that: contains('Flutter issue 2'))),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test('aborts if validation errors are present', () async {
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
when(flutterValidator.validate).thenAnswer(
|
||||
(_) async => [
|
||||
const ValidationIssue(
|
||||
severity: ValidationIssueSeverity.error,
|
||||
message: 'There was an issue',
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
|
||||
expect(exitCode, equals(ExitCode.config.code));
|
||||
verify(() => logger.err('Aborting due to validation errors.')).called(1);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ import 'package:shorebird_cli/src/code_push_client_wrapper.dart';
|
||||
import 'package:shorebird_cli/src/commands/commands.dart';
|
||||
import 'package:shorebird_cli/src/ios_deploy.dart';
|
||||
import 'package:shorebird_cli/src/logger.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validator.dart';
|
||||
import 'package:shorebird_code_push_client/shorebird_code_push_client.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
@@ -52,6 +53,8 @@ class _MockReleaseArtifact extends Mock implements ReleaseArtifact {}
|
||||
|
||||
class _MockIOSDeploy extends Mock implements IOSDeploy {}
|
||||
|
||||
class _MockShorebirdValidator extends Mock implements ShorebirdValidator {}
|
||||
|
||||
void main() {
|
||||
group(PreviewCommand, () {
|
||||
const appId = 'test-app-id';
|
||||
@@ -72,6 +75,7 @@ void main() {
|
||||
late Progress progress;
|
||||
late Release release;
|
||||
late ReleaseArtifact releaseArtifact;
|
||||
late ShorebirdValidator shorebirdValidator;
|
||||
late PreviewCommand command;
|
||||
|
||||
R runWithOverrides<R>(R Function() body) {
|
||||
@@ -83,6 +87,7 @@ void main() {
|
||||
cacheRef.overrideWith(() => cache),
|
||||
codePushClientWrapperRef.overrideWith(() => codePushClientWrapper),
|
||||
loggerRef.overrideWith(() => logger),
|
||||
shorebirdValidatorRef.overrideWith(() => shorebirdValidator),
|
||||
},
|
||||
),
|
||||
createHttpClient: (_) => httpClient,
|
||||
@@ -109,6 +114,7 @@ void main() {
|
||||
progress = _MockProgress();
|
||||
release = _MockRelease();
|
||||
releaseArtifact = _MockReleaseArtifact();
|
||||
shorebirdValidator = _MockShorebirdValidator();
|
||||
command = PreviewCommand()..testArgResults = argResults;
|
||||
|
||||
when(() => argResults['app-id']).thenReturn(appId);
|
||||
@@ -138,12 +144,29 @@ void main() {
|
||||
ReleasePlatform.ios: ReleaseStatus.active,
|
||||
});
|
||||
when(() => logger.progress(any())).thenReturn(progress);
|
||||
when(
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: any(named: 'checkUserIsAuthenticated'),
|
||||
),
|
||||
).thenAnswer((_) async {});
|
||||
});
|
||||
|
||||
test('returns no user error when not logged in', () async {
|
||||
when(() => auth.isAuthenticated).thenReturn(false);
|
||||
final result = await runWithOverrides(command.run);
|
||||
expect(result, ExitCode.noUser.code);
|
||||
test('exits when validation fails', () async {
|
||||
final exception = ValidationFailedException();
|
||||
when(
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: any(named: 'checkUserIsAuthenticated'),
|
||||
),
|
||||
).thenThrow(exception);
|
||||
await expectLater(
|
||||
runWithOverrides(command.run),
|
||||
completion(equals(exception.exitCode.code)),
|
||||
);
|
||||
verify(
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: true,
|
||||
),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test('exits with code 70 when querying for releases fails', () async {
|
||||
@@ -191,6 +214,7 @@ void main() {
|
||||
codePushClientWrapperRef
|
||||
.overrideWith(() => codePushClientWrapper),
|
||||
loggerRef.overrideWith(() => logger),
|
||||
shorebirdValidatorRef.overrideWith(() => shorebirdValidator),
|
||||
},
|
||||
),
|
||||
createHttpClient: (_) => httpClient,
|
||||
@@ -485,6 +509,7 @@ void main() {
|
||||
.overrideWith(() => codePushClientWrapper),
|
||||
iosDeployRef.overrideWith(() => iosDeploy),
|
||||
loggerRef.overrideWith(() => logger),
|
||||
shorebirdValidatorRef.overrideWith(() => shorebirdValidator),
|
||||
},
|
||||
),
|
||||
createHttpClient: (_) => httpClient,
|
||||
@@ -505,8 +530,8 @@ void main() {
|
||||
.thenAnswer((invocation) async {
|
||||
(invocation.positionalArguments.single as IOSink)
|
||||
.add(ZipEncoder().encode(Archive())!);
|
||||
// Wait 1 tick for the content to be written.
|
||||
await Future<void>.delayed(Duration.zero);
|
||||
// Wait for Isolate to finish.
|
||||
await Future<void>.delayed(const Duration(milliseconds: 1));
|
||||
});
|
||||
when(
|
||||
() => iosDeploy.installAndLaunchApp(
|
||||
|
||||
@@ -15,6 +15,7 @@ import 'package:shorebird_cli/src/logger.dart';
|
||||
import 'package:shorebird_cli/src/platform.dart';
|
||||
import 'package:shorebird_cli/src/process.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_build_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validator.dart';
|
||||
import 'package:shorebird_code_push_client/shorebird_code_push_client.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
@@ -39,14 +40,18 @@ class _MockCodePushClientWrapper extends Mock
|
||||
|
||||
class _MockShorebirdProcess extends Mock implements ShorebirdProcess {}
|
||||
|
||||
class _MockShorebirdValidator extends Mock implements ShorebirdValidator {}
|
||||
|
||||
class _FakeRelease extends Fake implements Release {}
|
||||
|
||||
class _FakeShorebirdProcess extends Fake implements ShorebirdProcess {}
|
||||
|
||||
void main() {
|
||||
group(ReleaseAarCommand, () {
|
||||
const appDisplayName = 'Test App';
|
||||
const appId = 'test-app-id';
|
||||
const appMetadata = AppMetadata(appId: appId, displayName: appDisplayName);
|
||||
|
||||
const flutterRevision = '83305b5088e6fe327fb3334a73ff190828d85713';
|
||||
|
||||
const versionName = '1.2.3';
|
||||
const versionCode = '1';
|
||||
const version = '$versionName+$versionCode';
|
||||
@@ -58,7 +63,6 @@ void main() {
|
||||
displayName: '1.2.3+1',
|
||||
platformStatuses: {},
|
||||
);
|
||||
|
||||
const releasePlatform = ReleasePlatform.android;
|
||||
const buildNumber = '1.0';
|
||||
const noModulePubspecYamlContent = '''
|
||||
@@ -96,8 +100,9 @@ flutter:
|
||||
late Logger logger;
|
||||
late ShorebirdProcessResult flutterBuildProcessResult;
|
||||
late ShorebirdProcessResult flutterRevisionProcessResult;
|
||||
late ReleaseAarCommand command;
|
||||
late ShorebirdProcess shorebirdProcess;
|
||||
late ShorebirdValidator shorebirdValidator;
|
||||
late ReleaseAarCommand command;
|
||||
|
||||
R runWithOverrides<R>(R Function() body) {
|
||||
return runScoped(
|
||||
@@ -110,6 +115,7 @@ flutter:
|
||||
loggerRef.overrideWith(() => logger),
|
||||
platformRef.overrideWith(() => platform),
|
||||
processRef.overrideWith(() => shorebirdProcess),
|
||||
shorebirdValidatorRef.overrideWith(() => shorebirdValidator),
|
||||
},
|
||||
);
|
||||
}
|
||||
@@ -158,6 +164,8 @@ flutter:
|
||||
setUpAll(() {
|
||||
registerFallbackValue(ReleasePlatform.android);
|
||||
registerFallbackValue(ReleaseStatus.draft);
|
||||
registerFallbackValue(_FakeRelease());
|
||||
registerFallbackValue(_FakeShorebirdProcess());
|
||||
});
|
||||
|
||||
setUp(() {
|
||||
@@ -173,9 +181,7 @@ flutter:
|
||||
flutterRevisionProcessResult = _MockProcessResult();
|
||||
shorebirdProcess = _MockShorebirdProcess();
|
||||
shorebirdRoot = Directory.systemTemp.createTempSync();
|
||||
|
||||
registerFallbackValue(release);
|
||||
registerFallbackValue(shorebirdProcess);
|
||||
shorebirdValidator = _MockShorebirdValidator();
|
||||
|
||||
when(() => auth.client).thenReturn(httpClient);
|
||||
when(() => argResults['build-number']).thenReturn(buildNumber);
|
||||
@@ -266,6 +272,13 @@ flutter:
|
||||
),
|
||||
).thenAnswer((_) async => {});
|
||||
|
||||
when(
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: any(named: 'checkUserIsAuthenticated'),
|
||||
checkShorebirdInitialized: any(named: 'checkShorebirdInitialized'),
|
||||
),
|
||||
).thenAnswer((_) async {});
|
||||
|
||||
command = runWithOverrides(
|
||||
() => ReleaseAarCommand(unzipFn: (_, __) async {}),
|
||||
)..testArgResults = argResults;
|
||||
@@ -275,34 +288,23 @@ flutter:
|
||||
expect(command.description, isNotEmpty);
|
||||
});
|
||||
|
||||
test('throws config error when shorebird is not initialized', () async {
|
||||
final tempDir = Directory.systemTemp.createTempSync();
|
||||
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
|
||||
verify(
|
||||
() => logger.err(
|
||||
'Shorebird is not initialized. Did you run "shorebird init"?',
|
||||
test('exits when validation fails', () async {
|
||||
final exception = ValidationFailedException();
|
||||
when(
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: any(named: 'checkUserIsAuthenticated'),
|
||||
checkShorebirdInitialized: any(named: 'checkShorebirdInitialized'),
|
||||
),
|
||||
).called(1);
|
||||
expect(exitCode, ExitCode.config.code);
|
||||
});
|
||||
|
||||
test('exits with no user when not logged in', () async {
|
||||
when(() => auth.isAuthenticated).thenReturn(false);
|
||||
final tempDir = setUpTempDir(includeModule: false);
|
||||
|
||||
final result = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
).thenThrow(exception);
|
||||
await expectLater(
|
||||
runWithOverrides(command.run),
|
||||
completion(equals(exception.exitCode.code)),
|
||||
);
|
||||
|
||||
expect(result, equals(ExitCode.noUser.code));
|
||||
verify(
|
||||
() => logger.err(any(that: contains('You must be logged in to run'))),
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: true,
|
||||
checkShorebirdInitialized: true,
|
||||
),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
|
||||
+37
-81
@@ -17,6 +17,7 @@ import 'package:shorebird_cli/src/java.dart';
|
||||
import 'package:shorebird_cli/src/logger.dart';
|
||||
import 'package:shorebird_cli/src/platform.dart';
|
||||
import 'package:shorebird_cli/src/process.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validator.dart';
|
||||
import 'package:shorebird_cli/src/validators/validators.dart';
|
||||
import 'package:shorebird_code_push_client/shorebird_code_push_client.dart';
|
||||
import 'package:test/test.dart';
|
||||
@@ -49,8 +50,14 @@ class _MockShorebirdFlutterValidator extends Mock
|
||||
|
||||
class _MockShorebirdProcess extends Mock implements ShorebirdProcess {}
|
||||
|
||||
class _MockShorebirdValidator extends Mock implements ShorebirdValidator {}
|
||||
|
||||
class _MockJava extends Mock implements Java {}
|
||||
|
||||
class _FakeRelease extends Fake implements Release {}
|
||||
|
||||
class _FakeShorebirdProcess extends Fake implements ShorebirdProcess {}
|
||||
|
||||
void main() {
|
||||
group(ReleaseAndroidCommand, () {
|
||||
const appId = 'test-app-id';
|
||||
@@ -97,9 +104,10 @@ flutter:
|
||||
late Logger logger;
|
||||
late ShorebirdProcessResult flutterBuildProcessResult;
|
||||
late ShorebirdProcessResult flutterRevisionProcessResult;
|
||||
late ReleaseAndroidCommand command;
|
||||
late ShorebirdFlutterValidator flutterValidator;
|
||||
late ShorebirdProcess shorebirdProcess;
|
||||
late ShorebirdValidator shorebirdValidator;
|
||||
late ReleaseAndroidCommand command;
|
||||
|
||||
R runWithOverrides<R>(R Function() body) {
|
||||
return runScoped(
|
||||
@@ -115,6 +123,7 @@ flutter:
|
||||
loggerRef.overrideWith(() => logger),
|
||||
platformRef.overrideWith(() => platform),
|
||||
processRef.overrideWith(() => shorebirdProcess),
|
||||
shorebirdValidatorRef.overrideWith(() => shorebirdValidator),
|
||||
},
|
||||
);
|
||||
}
|
||||
@@ -133,6 +142,8 @@ flutter:
|
||||
setUpAll(() {
|
||||
registerFallbackValue(ReleasePlatform.android);
|
||||
registerFallbackValue(ReleaseStatus.draft);
|
||||
registerFallbackValue(_FakeRelease());
|
||||
registerFallbackValue(_FakeShorebirdProcess());
|
||||
});
|
||||
|
||||
setUp(() {
|
||||
@@ -152,9 +163,7 @@ flutter:
|
||||
flutterRevisionProcessResult = _MockProcessResult();
|
||||
flutterValidator = _MockShorebirdFlutterValidator();
|
||||
shorebirdProcess = _MockShorebirdProcess();
|
||||
|
||||
registerFallbackValue(release);
|
||||
registerFallbackValue(shorebirdProcess);
|
||||
shorebirdValidator = _MockShorebirdValidator();
|
||||
|
||||
when(() => platform.script).thenReturn(
|
||||
Uri.file(
|
||||
@@ -256,6 +265,14 @@ flutter:
|
||||
when(
|
||||
() => bundletool.getVersionCode(any()),
|
||||
).thenAnswer((_) async => versionCode);
|
||||
when(
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: any(named: 'checkUserIsAuthenticated'),
|
||||
checkShorebirdInitialized: any(named: 'checkShorebirdInitialized'),
|
||||
validators: any(named: 'validators'),
|
||||
supportedOperatingSystems: any(named: 'supportedOperatingSystems'),
|
||||
),
|
||||
).thenAnswer((_) async {});
|
||||
|
||||
command = runWithOverrides(ReleaseAndroidCommand.new)
|
||||
..testArgResults = argResults;
|
||||
@@ -265,28 +282,26 @@ flutter:
|
||||
expect(command.description, isNotEmpty);
|
||||
});
|
||||
|
||||
test('throws config error when shorebird is not initialized', () async {
|
||||
final tempDir = Directory.systemTemp.createTempSync();
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
test('exits when validation fails', () async {
|
||||
final exception = ValidationFailedException();
|
||||
when(
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: any(named: 'checkUserIsAuthenticated'),
|
||||
checkShorebirdInitialized: any(named: 'checkShorebirdInitialized'),
|
||||
validators: any(named: 'validators'),
|
||||
),
|
||||
).thenThrow(exception);
|
||||
await expectLater(
|
||||
runWithOverrides(command.run),
|
||||
completion(equals(exception.exitCode.code)),
|
||||
);
|
||||
verify(
|
||||
() => logger.err(
|
||||
'Shorebird is not initialized. Did you run "shorebird init"?',
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: true,
|
||||
checkShorebirdInitialized: true,
|
||||
validators: [flutterValidator],
|
||||
),
|
||||
).called(1);
|
||||
expect(exitCode, ExitCode.config.code);
|
||||
});
|
||||
|
||||
test('throws no user error when user is not logged in', () async {
|
||||
when(() => auth.isAuthenticated).thenReturn(false);
|
||||
final tempDir = setUpTempDir();
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
expect(exitCode, equals(ExitCode.noUser.code));
|
||||
});
|
||||
|
||||
test('exits with code 70 when building fails', () async {
|
||||
@@ -525,64 +540,5 @@ flavors:
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
test('prints flutter validation warnings', () async {
|
||||
when(flutterValidator.validate).thenAnswer(
|
||||
(_) async => [
|
||||
const ValidationIssue(
|
||||
severity: ValidationIssueSeverity.warning,
|
||||
message: 'Flutter issue 1',
|
||||
),
|
||||
const ValidationIssue(
|
||||
severity: ValidationIssueSeverity.warning,
|
||||
message: 'Flutter issue 2',
|
||||
),
|
||||
],
|
||||
);
|
||||
final tempDir = setUpTempDir();
|
||||
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
|
||||
verify(() => logger.success('\n✅ Published Release!')).called(1);
|
||||
expect(exitCode, ExitCode.success.code);
|
||||
verify(
|
||||
() => logger.info(any(that: contains('Flutter issue 1'))),
|
||||
).called(1);
|
||||
verify(
|
||||
() => logger.info(any(that: contains('Flutter issue 2'))),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test('aborts if validation errors are present', () async {
|
||||
when(flutterValidator.validate).thenAnswer(
|
||||
(_) async => [
|
||||
const ValidationIssue(
|
||||
severity: ValidationIssueSeverity.error,
|
||||
message: 'There was an issue',
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
final tempDir = setUpTempDir();
|
||||
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
|
||||
expect(exitCode, equals(ExitCode.config.code));
|
||||
verify(() => logger.err('Aborting due to validation errors.')).called(1);
|
||||
verifyNever(
|
||||
() => codePushClientWrapper.updateReleaseStatus(
|
||||
appId: any(named: 'appId'),
|
||||
releaseId: any(named: 'releaseId'),
|
||||
platform: any(named: 'platform'),
|
||||
status: any(named: 'status'),
|
||||
),
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ import 'package:shorebird_cli/src/doctor.dart';
|
||||
import 'package:shorebird_cli/src/logger.dart';
|
||||
import 'package:shorebird_cli/src/platform.dart';
|
||||
import 'package:shorebird_cli/src/process.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validator.dart';
|
||||
import 'package:shorebird_cli/src/validators/validators.dart';
|
||||
import 'package:shorebird_code_push_client/shorebird_code_push_client.dart';
|
||||
import 'package:test/test.dart';
|
||||
@@ -45,6 +46,12 @@ class _MockShorebirdFlutterValidator extends Mock
|
||||
|
||||
class _MockShorebirdProcess extends Mock implements ShorebirdProcess {}
|
||||
|
||||
class _MockShorebirdValidator extends Mock implements ShorebirdValidator {}
|
||||
|
||||
class _FakeRelease extends Fake implements Release {}
|
||||
|
||||
class _FakeShorebirdProcess extends Fake implements ShorebirdProcess {}
|
||||
|
||||
void main() {
|
||||
group(ReleaseIosCommand, () {
|
||||
const appId = 'test-app-id';
|
||||
@@ -95,9 +102,10 @@ flutter:
|
||||
late Logger logger;
|
||||
late ShorebirdProcessResult flutterBuildProcessResult;
|
||||
late ShorebirdProcessResult flutterRevisionProcessResult;
|
||||
late ReleaseIosCommand command;
|
||||
late ShorebirdFlutterValidator flutterValidator;
|
||||
late ShorebirdProcess shorebirdProcess;
|
||||
late ShorebirdValidator shorebirdValidator;
|
||||
late ReleaseIosCommand command;
|
||||
|
||||
R runWithOverrides<R>(R Function() body) {
|
||||
return runScoped(
|
||||
@@ -109,6 +117,7 @@ flutter:
|
||||
loggerRef.overrideWith(() => logger),
|
||||
platformRef.overrideWith(() => platform),
|
||||
processRef.overrideWith(() => shorebirdProcess),
|
||||
shorebirdValidatorRef.overrideWith(() => shorebirdValidator),
|
||||
},
|
||||
);
|
||||
}
|
||||
@@ -132,6 +141,8 @@ flutter:
|
||||
setUpAll(() {
|
||||
registerFallbackValue(ReleasePlatform.ios);
|
||||
registerFallbackValue(ReleaseStatus.draft);
|
||||
registerFallbackValue(_FakeRelease());
|
||||
registerFallbackValue(_FakeShorebirdProcess());
|
||||
});
|
||||
|
||||
setUp(() {
|
||||
@@ -149,9 +160,7 @@ flutter:
|
||||
flutterRevisionProcessResult = _MockProcessResult();
|
||||
flutterValidator = _MockShorebirdFlutterValidator();
|
||||
shorebirdProcess = _MockShorebirdProcess();
|
||||
|
||||
registerFallbackValue(release);
|
||||
registerFallbackValue(shorebirdProcess);
|
||||
shorebirdValidator = _MockShorebirdValidator();
|
||||
|
||||
when(() => platform.script).thenReturn(
|
||||
Uri.file(
|
||||
@@ -240,7 +249,14 @@ flutter:
|
||||
).thenAnswer((_) async => {});
|
||||
|
||||
when(() => doctor.iosCommandValidators).thenReturn([flutterValidator]);
|
||||
when(flutterValidator.validate).thenAnswer((_) async => []);
|
||||
when(
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: any(named: 'checkUserIsAuthenticated'),
|
||||
checkShorebirdInitialized: any(named: 'checkShorebirdInitialized'),
|
||||
validators: any(named: 'validators'),
|
||||
supportedOperatingSystems: any(named: 'supportedOperatingSystems'),
|
||||
),
|
||||
).thenAnswer((_) async {});
|
||||
|
||||
command = runWithOverrides(() => ReleaseIosCommand(ipaReader: ipaReader))
|
||||
..testArgResults = argResults;
|
||||
@@ -250,38 +266,28 @@ flutter:
|
||||
expect(command.description, isNotEmpty);
|
||||
});
|
||||
|
||||
test('exits with unavailable code if run on non-macOS platform', () async {
|
||||
when(() => platform.operatingSystem).thenReturn(Platform.windows);
|
||||
|
||||
final result = await runWithOverrides(command.run);
|
||||
|
||||
expect(result, equals(ExitCode.unavailable.code));
|
||||
verify(() => logger.err('This command is only supported on macos.'))
|
||||
.called(1);
|
||||
});
|
||||
|
||||
test('throws config error when shorebird is not initialized', () async {
|
||||
final tempDir = Directory.systemTemp.createTempSync();
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
test('exits when validation fails', () async {
|
||||
final exception = ValidationFailedException();
|
||||
when(
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: any(named: 'checkUserIsAuthenticated'),
|
||||
checkShorebirdInitialized: any(named: 'checkShorebirdInitialized'),
|
||||
validators: any(named: 'validators'),
|
||||
supportedOperatingSystems: any(named: 'supportedOperatingSystems'),
|
||||
),
|
||||
).thenThrow(exception);
|
||||
await expectLater(
|
||||
runWithOverrides(command.run),
|
||||
completion(equals(exception.exitCode.code)),
|
||||
);
|
||||
verify(
|
||||
() => logger.err(
|
||||
'Shorebird is not initialized. Did you run "shorebird init"?',
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: true,
|
||||
checkShorebirdInitialized: true,
|
||||
validators: [flutterValidator],
|
||||
supportedOperatingSystems: {Platform.macOS},
|
||||
),
|
||||
).called(1);
|
||||
expect(exitCode, ExitCode.config.code);
|
||||
});
|
||||
|
||||
test('throws no user error when user is not logged in', () async {
|
||||
when(() => auth.isAuthenticated).thenReturn(false);
|
||||
final tempDir = setUpTempDir();
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
expect(exitCode, equals(ExitCode.noUser.code));
|
||||
});
|
||||
|
||||
test('exits with code 70 when build fails with non-zero exit code',
|
||||
@@ -356,54 +362,6 @@ error: exportArchive: No signing certificate "iOS Distribution" found
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test('prints flutter validation warnings', () async {
|
||||
when(flutterValidator.validate).thenAnswer(
|
||||
(_) async => [
|
||||
const ValidationIssue(
|
||||
severity: ValidationIssueSeverity.warning,
|
||||
message: 'Flutter issue 1',
|
||||
),
|
||||
const ValidationIssue(
|
||||
severity: ValidationIssueSeverity.warning,
|
||||
message: 'Flutter issue 2',
|
||||
),
|
||||
],
|
||||
);
|
||||
final tempDir = setUpTempDir();
|
||||
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
|
||||
expect(exitCode, ExitCode.success.code);
|
||||
verify(
|
||||
() => logger.info(any(that: contains('Flutter issue 1'))),
|
||||
).called(1);
|
||||
verify(
|
||||
() => logger.info(any(that: contains('Flutter issue 2'))),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test('aborts if validation errors are present', () async {
|
||||
when(flutterValidator.validate).thenAnswer(
|
||||
(_) async => [
|
||||
const ValidationIssue(
|
||||
severity: ValidationIssueSeverity.error,
|
||||
message: 'There was an issue',
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
final tempDir = setUpTempDir();
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
expect(exitCode, equals(ExitCode.config.code));
|
||||
verify(() => logger.err('Aborting due to validation errors.')).called(1);
|
||||
});
|
||||
|
||||
test('aborts when user opts out', () async {
|
||||
when(() => logger.confirm(any())).thenReturn(false);
|
||||
final tempDir = setUpTempDir();
|
||||
|
||||
+39
-81
@@ -13,6 +13,7 @@ import 'package:shorebird_cli/src/doctor.dart';
|
||||
import 'package:shorebird_cli/src/logger.dart';
|
||||
import 'package:shorebird_cli/src/platform.dart';
|
||||
import 'package:shorebird_cli/src/process.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validator.dart';
|
||||
import 'package:shorebird_cli/src/validators/validators.dart';
|
||||
import 'package:shorebird_code_push_client/shorebird_code_push_client.dart';
|
||||
import 'package:test/test.dart';
|
||||
@@ -39,6 +40,12 @@ class _MockShorebirdFlutterValidator extends Mock
|
||||
|
||||
class _MockShorebirdProcess extends Mock implements ShorebirdProcess {}
|
||||
|
||||
class _MockShorebirdValidator extends Mock implements ShorebirdValidator {}
|
||||
|
||||
class _FakeRelease extends Fake implements Release {}
|
||||
|
||||
class _FakeShorebirdProcess extends Fake implements ShorebirdProcess {}
|
||||
|
||||
void main() {
|
||||
group(ReleaseIosFrameworkCommand, () {
|
||||
const appId = 'test-app-id';
|
||||
@@ -77,9 +84,10 @@ flutter:
|
||||
late Logger logger;
|
||||
late ShorebirdProcessResult flutterBuildProcessResult;
|
||||
late ShorebirdProcessResult flutterRevisionProcessResult;
|
||||
late ReleaseIosFrameworkCommand command;
|
||||
late ShorebirdFlutterValidator flutterValidator;
|
||||
late ShorebirdProcess shorebirdProcess;
|
||||
late ShorebirdValidator shorebirdValidator;
|
||||
late ReleaseIosFrameworkCommand command;
|
||||
|
||||
R runWithOverrides<R>(R Function() body) {
|
||||
return runScoped(
|
||||
@@ -91,6 +99,7 @@ flutter:
|
||||
loggerRef.overrideWith(() => logger),
|
||||
platformRef.overrideWith(() => platform),
|
||||
processRef.overrideWith(() => shorebirdProcess),
|
||||
shorebirdValidatorRef.overrideWith(() => shorebirdValidator),
|
||||
},
|
||||
);
|
||||
}
|
||||
@@ -109,6 +118,8 @@ flutter:
|
||||
setUpAll(() {
|
||||
registerFallbackValue(ReleasePlatform.ios);
|
||||
registerFallbackValue(ReleaseStatus.draft);
|
||||
registerFallbackValue(_FakeRelease());
|
||||
registerFallbackValue(_FakeShorebirdProcess());
|
||||
});
|
||||
|
||||
setUp(() {
|
||||
@@ -124,9 +135,7 @@ flutter:
|
||||
flutterRevisionProcessResult = _MockProcessResult();
|
||||
flutterValidator = _MockShorebirdFlutterValidator();
|
||||
shorebirdProcess = _MockShorebirdProcess();
|
||||
|
||||
registerFallbackValue(release);
|
||||
registerFallbackValue(shorebirdProcess);
|
||||
shorebirdValidator = _MockShorebirdValidator();
|
||||
|
||||
when(() => platform.script).thenReturn(
|
||||
Uri.file(
|
||||
@@ -167,7 +176,6 @@ flutter:
|
||||
when(
|
||||
() => flutterRevisionProcessResult.stdout,
|
||||
).thenReturn(flutterRevision);
|
||||
when(flutterValidator.validate).thenAnswer((_) async => []);
|
||||
when(() => logger.progress(any())).thenReturn(progress);
|
||||
when(() => logger.confirm(any())).thenReturn(true);
|
||||
when(() => platform.operatingSystem).thenReturn(Platform.macOS);
|
||||
@@ -209,6 +217,14 @@ flutter:
|
||||
status: any(named: 'status'),
|
||||
),
|
||||
).thenAnswer((_) async => {});
|
||||
when(
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: any(named: 'checkUserIsAuthenticated'),
|
||||
checkShorebirdInitialized: any(named: 'checkShorebirdInitialized'),
|
||||
validators: any(named: 'validators'),
|
||||
supportedOperatingSystems: any(named: 'supportedOperatingSystems'),
|
||||
),
|
||||
).thenAnswer((_) async {});
|
||||
|
||||
command = runWithOverrides(ReleaseIosFrameworkCommand.new)
|
||||
..testArgResults = argResults;
|
||||
@@ -218,38 +234,28 @@ flutter:
|
||||
expect(command.description, isNotEmpty);
|
||||
});
|
||||
|
||||
test('exits with unavailable code if run on non-macOS platform', () async {
|
||||
when(() => platform.operatingSystem).thenReturn(Platform.windows);
|
||||
|
||||
final result = await runWithOverrides(command.run);
|
||||
|
||||
expect(result, equals(ExitCode.unavailable.code));
|
||||
verify(() => logger.err('This command is only supported on macos.'))
|
||||
.called(1);
|
||||
});
|
||||
|
||||
test('throws config error when shorebird is not initialized', () async {
|
||||
final tempDir = Directory.systemTemp.createTempSync();
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
test('exits when validation fails', () async {
|
||||
final exception = ValidationFailedException();
|
||||
when(
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: any(named: 'checkUserIsAuthenticated'),
|
||||
checkShorebirdInitialized: any(named: 'checkShorebirdInitialized'),
|
||||
validators: any(named: 'validators'),
|
||||
supportedOperatingSystems: any(named: 'supportedOperatingSystems'),
|
||||
),
|
||||
).thenThrow(exception);
|
||||
await expectLater(
|
||||
runWithOverrides(command.run),
|
||||
completion(equals(exception.exitCode.code)),
|
||||
);
|
||||
verify(
|
||||
() => logger.err(
|
||||
'Shorebird is not initialized. Did you run "shorebird init"?',
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: true,
|
||||
checkShorebirdInitialized: true,
|
||||
validators: [flutterValidator],
|
||||
supportedOperatingSystems: {Platform.macOS},
|
||||
),
|
||||
).called(1);
|
||||
expect(exitCode, ExitCode.config.code);
|
||||
});
|
||||
|
||||
test('throws no user error when user is not logged in', () async {
|
||||
when(() => auth.isAuthenticated).thenReturn(false);
|
||||
final tempDir = setUpTempDir();
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
expect(exitCode, equals(ExitCode.noUser.code));
|
||||
});
|
||||
|
||||
test('exits with code 70 when build fails with non-zero exit code',
|
||||
@@ -269,54 +275,6 @@ flutter:
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test('prints flutter validation warnings', () async {
|
||||
when(flutterValidator.validate).thenAnswer(
|
||||
(_) async => [
|
||||
const ValidationIssue(
|
||||
severity: ValidationIssueSeverity.warning,
|
||||
message: 'Flutter issue 1',
|
||||
),
|
||||
const ValidationIssue(
|
||||
severity: ValidationIssueSeverity.warning,
|
||||
message: 'Flutter issue 2',
|
||||
),
|
||||
],
|
||||
);
|
||||
final tempDir = setUpTempDir();
|
||||
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
|
||||
expect(exitCode, ExitCode.success.code);
|
||||
verify(
|
||||
() => logger.info(any(that: contains('Flutter issue 1'))),
|
||||
).called(1);
|
||||
verify(
|
||||
() => logger.info(any(that: contains('Flutter issue 2'))),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test('aborts if validation errors are present', () async {
|
||||
when(flutterValidator.validate).thenAnswer(
|
||||
(_) async => [
|
||||
const ValidationIssue(
|
||||
severity: ValidationIssueSeverity.error,
|
||||
message: 'There was an issue',
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
final tempDir = setUpTempDir();
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
expect(exitCode, equals(ExitCode.config.code));
|
||||
verify(() => logger.err('Aborting due to validation errors.')).called(1);
|
||||
});
|
||||
|
||||
test('checks that release is not active if release exists', () async {
|
||||
when(
|
||||
() => codePushClientWrapper.maybeGetRelease(
|
||||
|
||||
+32
-13
@@ -9,6 +9,7 @@ import 'package:scoped/scoped.dart';
|
||||
import 'package:shorebird_cli/src/auth/auth.dart';
|
||||
import 'package:shorebird_cli/src/commands/releases/releases.dart';
|
||||
import 'package:shorebird_cli/src/logger.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validator.dart';
|
||||
import 'package:shorebird_code_push_client/shorebird_code_push_client.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
@@ -24,6 +25,8 @@ class _MockLogger extends Mock implements Logger {}
|
||||
|
||||
class _MockProgress extends Mock implements Progress {}
|
||||
|
||||
class _MockShorebirdValidator extends Mock implements ShorebirdValidator {}
|
||||
|
||||
void main() {
|
||||
group(DeleteReleasesCommand, () {
|
||||
const appId = 'test-app-id';
|
||||
@@ -47,6 +50,7 @@ flutter:
|
||||
late Logger logger;
|
||||
late CodePushClient codePushClient;
|
||||
late Progress progress;
|
||||
late ShorebirdValidator shorebirdValidator;
|
||||
late DeleteReleasesCommand command;
|
||||
|
||||
R runWithOverrides<R>(R Function() body) {
|
||||
@@ -54,7 +58,8 @@ flutter:
|
||||
body,
|
||||
values: {
|
||||
authRef.overrideWith(() => auth),
|
||||
loggerRef.overrideWith(() => logger)
|
||||
loggerRef.overrideWith(() => logger),
|
||||
shorebirdValidatorRef.overrideWith(() => shorebirdValidator),
|
||||
},
|
||||
);
|
||||
}
|
||||
@@ -77,6 +82,7 @@ flutter:
|
||||
logger = _MockLogger();
|
||||
codePushClient = _MockCodePushClient();
|
||||
progress = _MockProgress();
|
||||
shorebirdValidator = _MockShorebirdValidator();
|
||||
|
||||
when(() => argResults['version']).thenReturn(versionNumber);
|
||||
|
||||
@@ -116,6 +122,13 @@ flutter:
|
||||
when(() => logger.confirm(any())).thenReturn(true);
|
||||
when(() => logger.progress(any())).thenReturn(progress);
|
||||
|
||||
when(
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: any(named: 'checkUserIsAuthenticated'),
|
||||
checkShorebirdInitialized: any(named: 'checkShorebirdInitialized'),
|
||||
),
|
||||
).thenAnswer((_) async {});
|
||||
|
||||
command = runWithOverrides(
|
||||
() => DeleteReleasesCommand(
|
||||
buildCodePushClient: ({
|
||||
@@ -135,18 +148,24 @@ flutter:
|
||||
);
|
||||
});
|
||||
|
||||
test('returns no user error when not logged in', () async {
|
||||
when(() => auth.isAuthenticated).thenReturn(false);
|
||||
|
||||
final result = await runWithOverrides(command.run);
|
||||
|
||||
expect(result, ExitCode.noUser.code);
|
||||
});
|
||||
|
||||
test('returns config exit code if shorebird.yaml is not present', () async {
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
|
||||
expect(exitCode, ExitCode.config.code);
|
||||
test('exits when validation fails', () async {
|
||||
final exception = ValidationFailedException();
|
||||
when(
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: any(named: 'checkUserIsAuthenticated'),
|
||||
checkShorebirdInitialized: any(named: 'checkShorebirdInitialized'),
|
||||
),
|
||||
).thenThrow(exception);
|
||||
await expectLater(
|
||||
runWithOverrides(command.run),
|
||||
completion(equals(exception.exitCode.code)),
|
||||
);
|
||||
verify(
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: true,
|
||||
checkShorebirdInitialized: true,
|
||||
),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test('prompts for version when not provided', () async {
|
||||
|
||||
@@ -9,6 +9,7 @@ import 'package:scoped/scoped.dart';
|
||||
import 'package:shorebird_cli/src/auth/auth.dart';
|
||||
import 'package:shorebird_cli/src/commands/commands.dart';
|
||||
import 'package:shorebird_cli/src/logger.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validator.dart';
|
||||
import 'package:shorebird_code_push_client/shorebird_code_push_client.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
@@ -22,6 +23,8 @@ class _MockHttpClient extends Mock implements http.Client {}
|
||||
|
||||
class _MockLogger extends Mock implements Logger {}
|
||||
|
||||
class _MockShorebirdValidator extends Mock implements ShorebirdValidator {}
|
||||
|
||||
void main() {
|
||||
group(ListReleasesCommand, () {
|
||||
const appId = 'test-app-id';
|
||||
@@ -32,6 +35,7 @@ void main() {
|
||||
late http.Client httpClient;
|
||||
late CodePushClient codePushClient;
|
||||
late Logger logger;
|
||||
late ShorebirdValidator shorebirdValidator;
|
||||
late ListReleasesCommand command;
|
||||
|
||||
const pubspecYamlContent = '''
|
||||
@@ -49,7 +53,8 @@ flutter:
|
||||
body,
|
||||
values: {
|
||||
authRef.overrideWith(() => auth),
|
||||
loggerRef.overrideWith(() => logger)
|
||||
loggerRef.overrideWith(() => logger),
|
||||
shorebirdValidatorRef.overrideWith(() => shorebirdValidator),
|
||||
},
|
||||
);
|
||||
}
|
||||
@@ -71,10 +76,18 @@ flutter:
|
||||
codePushClient = _MockCodePushClient();
|
||||
httpClient = _MockHttpClient();
|
||||
logger = _MockLogger();
|
||||
shorebirdValidator = _MockShorebirdValidator();
|
||||
|
||||
when(() => auth.client).thenReturn(httpClient);
|
||||
when(() => auth.isAuthenticated).thenReturn(true);
|
||||
|
||||
when(
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: any(named: 'checkUserIsAuthenticated'),
|
||||
checkShorebirdInitialized: any(named: 'checkShorebirdInitialized'),
|
||||
),
|
||||
).thenAnswer((_) async {});
|
||||
|
||||
command = runWithOverrides(
|
||||
() => ListReleasesCommand(
|
||||
buildCodePushClient: ({required httpClient, hostedUri}) {
|
||||
@@ -88,25 +101,24 @@ flutter:
|
||||
expect(command.description, equals('List all releases for this app.'));
|
||||
});
|
||||
|
||||
test('returns ExitCode.noUser when not logged in', () async {
|
||||
when(() => auth.isAuthenticated).thenReturn(false);
|
||||
expect(await runWithOverrides(command.run), ExitCode.noUser.code);
|
||||
});
|
||||
|
||||
test('returns ExitCode.config when shorebird is not initialized', () async {
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
|
||||
test('exits when validation fails', () async {
|
||||
final exception = ValidationFailedException();
|
||||
when(
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: any(named: 'checkUserIsAuthenticated'),
|
||||
checkShorebirdInitialized: any(named: 'checkShorebirdInitialized'),
|
||||
),
|
||||
).thenThrow(exception);
|
||||
await expectLater(
|
||||
runWithOverrides(command.run),
|
||||
completion(equals(exception.exitCode.code)),
|
||||
);
|
||||
verify(
|
||||
() => logger.err(
|
||||
any(
|
||||
that: stringContainsInOrder([
|
||||
'Shorebird is not initialized. Did you run',
|
||||
'shorebird init',
|
||||
]),
|
||||
),
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: true,
|
||||
checkShorebirdInitialized: true,
|
||||
),
|
||||
).called(1);
|
||||
expect(exitCode, ExitCode.config.code);
|
||||
});
|
||||
|
||||
test('returns ExitCode.software when unable to get releases', () async {
|
||||
|
||||
@@ -12,6 +12,7 @@ import 'package:shorebird_cli/src/commands/run_command.dart';
|
||||
import 'package:shorebird_cli/src/doctor.dart';
|
||||
import 'package:shorebird_cli/src/logger.dart';
|
||||
import 'package:shorebird_cli/src/process.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validator.dart';
|
||||
import 'package:shorebird_cli/src/validators/validators.dart';
|
||||
import 'package:shorebird_code_push_client/shorebird_code_push_client.dart';
|
||||
import 'package:test/test.dart';
|
||||
@@ -36,6 +37,8 @@ class _MockShorebirdProcess extends Mock implements ShorebirdProcess {}
|
||||
|
||||
class _MockIOSink extends Mock implements IOSink {}
|
||||
|
||||
class _MockShorebirdValidator extends Mock implements ShorebirdValidator {}
|
||||
|
||||
class _MockValidator extends Mock implements Validator {}
|
||||
|
||||
void main() {
|
||||
@@ -48,9 +51,10 @@ void main() {
|
||||
late Process process;
|
||||
late CodePushClient codePushClient;
|
||||
late ShorebirdProcess shorebirdProcess;
|
||||
late RunCommand command;
|
||||
late IOSink ioSink;
|
||||
late ShorebirdValidator shorebirdValidator;
|
||||
late Validator validator;
|
||||
late RunCommand command;
|
||||
|
||||
R runWithOverrides<R>(R Function() body) {
|
||||
return runScoped(
|
||||
@@ -60,6 +64,7 @@ void main() {
|
||||
doctorRef.overrideWith(() => doctor),
|
||||
loggerRef.overrideWith(() => logger),
|
||||
processRef.overrideWith(() => shorebirdProcess),
|
||||
shorebirdValidatorRef.overrideWith(() => shorebirdValidator),
|
||||
},
|
||||
);
|
||||
}
|
||||
@@ -78,6 +83,7 @@ void main() {
|
||||
shorebirdProcess = _MockShorebirdProcess();
|
||||
codePushClient = _MockCodePushClient();
|
||||
ioSink = _MockIOSink();
|
||||
shorebirdValidator = _MockShorebirdValidator();
|
||||
validator = _MockValidator();
|
||||
|
||||
when(
|
||||
@@ -93,7 +99,12 @@ void main() {
|
||||
when(() => doctor.allValidators).thenReturn([validator]);
|
||||
when(() => logger.progress(any())).thenReturn(_MockProgress());
|
||||
when(() => ioSink.addStream(any())).thenAnswer((_) async {});
|
||||
when(() => validator.validate()).thenAnswer((_) async => []);
|
||||
when(
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: any(named: 'checkUserIsAuthenticated'),
|
||||
validators: any(named: 'validators'),
|
||||
),
|
||||
).thenAnswer((_) async {});
|
||||
|
||||
command = runWithOverrides(
|
||||
() => RunCommand(
|
||||
@@ -125,35 +136,24 @@ Please use "shorebird preview" instead.'''),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test('exits with no user when not logged in', () async {
|
||||
when(() => auth.isAuthenticated).thenReturn(false);
|
||||
|
||||
final result = await runWithOverrides(command.run);
|
||||
expect(result, equals(ExitCode.noUser.code));
|
||||
|
||||
verify(
|
||||
() => logger.err(any(that: contains('You must be logged in to run'))),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test('aborts on validation errors', () async {
|
||||
when(() => validator.validate()).thenAnswer(
|
||||
(_) async => [
|
||||
const ValidationIssue(
|
||||
severity: ValidationIssueSeverity.error,
|
||||
message: 'Android issue',
|
||||
),
|
||||
],
|
||||
test('exits when validation fails', () async {
|
||||
final exception = ValidationFailedException();
|
||||
when(
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: any(named: 'checkUserIsAuthenticated'),
|
||||
validators: any(named: 'validators'),
|
||||
),
|
||||
).thenThrow(exception);
|
||||
await expectLater(
|
||||
runWithOverrides(command.run),
|
||||
completion(equals(exception.exitCode.code)),
|
||||
);
|
||||
|
||||
final result = await runWithOverrides(command.run);
|
||||
|
||||
await expectLater(result, equals(ExitCode.config.code));
|
||||
verify(
|
||||
() => logger.info(any(that: contains('Android issue'))),
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: true,
|
||||
validators: [validator],
|
||||
),
|
||||
).called(1);
|
||||
verify(() => logger.err('Aborting due to validation errors.')).called(1);
|
||||
verifyNever(() => logger.info('Running app...'));
|
||||
});
|
||||
|
||||
test('exits with code when running the app fails', () async {
|
||||
|
||||
@@ -0,0 +1,150 @@
|
||||
import 'package:mason_logger/mason_logger.dart';
|
||||
import 'package:mocktail/mocktail.dart';
|
||||
import 'package:platform/platform.dart';
|
||||
import 'package:scoped/scoped.dart';
|
||||
import 'package:shorebird_cli/src/auth/auth.dart';
|
||||
import 'package:shorebird_cli/src/logger.dart';
|
||||
import 'package:shorebird_cli/src/platform.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validator.dart';
|
||||
import 'package:shorebird_cli/src/validators/validators.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
class _MockAuth extends Mock implements Auth {}
|
||||
|
||||
class _MockLogger extends Mock implements Logger {}
|
||||
|
||||
class _MockPlatform extends Mock implements Platform {}
|
||||
|
||||
class _MockValidator extends Mock implements Validator {}
|
||||
|
||||
void main() {
|
||||
group(ShorebirdValidator, () {
|
||||
late Auth auth;
|
||||
late Logger logger;
|
||||
late Platform platform;
|
||||
late Validator validator;
|
||||
late ShorebirdValidator shorebirdValidator;
|
||||
|
||||
R runWithOverrides<R>(R Function() body) {
|
||||
return runScoped(
|
||||
() => body(),
|
||||
values: {
|
||||
authRef.overrideWith(() => auth),
|
||||
loggerRef.overrideWith(() => logger),
|
||||
platformRef.overrideWith(() => platform),
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
setUp(() {
|
||||
auth = _MockAuth();
|
||||
logger = _MockLogger();
|
||||
platform = _MockPlatform();
|
||||
validator = _MockValidator();
|
||||
shorebirdValidator = runWithOverrides(ShorebirdValidator.new);
|
||||
});
|
||||
|
||||
group('PreconditionFailedException', () {
|
||||
test('have correct exit codes', () {
|
||||
expect(ShorebirdNotInitializedException().exitCode, ExitCode.config);
|
||||
expect(UserNotAuthorizedException().exitCode, ExitCode.noUser);
|
||||
expect(ValidationFailedException().exitCode, ExitCode.config);
|
||||
expect(
|
||||
UnsupportedOperatingSystemException().exitCode,
|
||||
ExitCode.unavailable,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
group('validatePreconditions', () {
|
||||
test(
|
||||
'throws UnsupportedOperatingSystemException '
|
||||
'when the operating system is not supported', () async {
|
||||
when(() => platform.operatingSystem).thenReturn(Platform.linux);
|
||||
const supportedOperatingSystems = {Platform.macOS, Platform.windows};
|
||||
await expectLater(
|
||||
runWithOverrides(
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
supportedOperatingSystems: supportedOperatingSystems,
|
||||
),
|
||||
),
|
||||
throwsA(isA<UnsupportedOperatingSystemException>()),
|
||||
);
|
||||
verify(
|
||||
() => logger.err(
|
||||
'''This command is only supported on ${supportedOperatingSystems.join(' ,')}.''',
|
||||
),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test(
|
||||
'throws UserNotAuthorizedException '
|
||||
'when user is not authenticated', () async {
|
||||
when(() => auth.isAuthenticated).thenReturn(false);
|
||||
await expectLater(
|
||||
runWithOverrides(
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: true,
|
||||
),
|
||||
),
|
||||
throwsA(isA<UserNotAuthorizedException>()),
|
||||
);
|
||||
verifyInOrder([
|
||||
() => logger.err('You must be logged in to run this command.'),
|
||||
() => logger.info(
|
||||
'''If you already have an account, run ${lightCyan.wrap('shorebird login')} to sign in.''',
|
||||
),
|
||||
() => logger.info(
|
||||
'''If you don't have a Shorebird account, run ${lightCyan.wrap('shorebird account create')} to create one.''',
|
||||
),
|
||||
]);
|
||||
});
|
||||
|
||||
test(
|
||||
'throws ShorebirdNotInitializedException '
|
||||
'when shorebird has not been initialized', () async {
|
||||
await expectLater(
|
||||
runWithOverrides(
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
checkShorebirdInitialized: true,
|
||||
),
|
||||
),
|
||||
throwsA(isA<ShorebirdNotInitializedException>()),
|
||||
);
|
||||
verify(
|
||||
() => logger.err(
|
||||
'Shorebird is not initialized. Did you run "shorebird init"?',
|
||||
),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test('throws ValidationFailedException if validator fails', () async {
|
||||
final issue = ValidationIssue(
|
||||
message: 'test issue',
|
||||
severity: ValidationIssueSeverity.error,
|
||||
fix: () async {},
|
||||
);
|
||||
when(() => validator.canRunInCurrentContext()).thenReturn(true);
|
||||
when(() => validator.validate()).thenAnswer((_) async => [issue]);
|
||||
await expectLater(
|
||||
runWithOverrides(
|
||||
() => shorebirdValidator.validatePreconditions(
|
||||
validators: [validator],
|
||||
),
|
||||
),
|
||||
throwsA(isA<ValidationFailedException>()),
|
||||
);
|
||||
verify(() => validator.validate()).called(1);
|
||||
verify(
|
||||
() => logger.err('Aborting due to validation errors.'),
|
||||
).called(1);
|
||||
verify(() => logger.info('[✗] ${issue.message}')).called(1);
|
||||
verify(
|
||||
() => logger.info(
|
||||
'''1 issue can be fixed automatically with ${lightCyan.wrap('shorebird doctor --fix')}.''',
|
||||
),
|
||||
).called(1);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user