mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
[tools]Build IPA validation UI Polish (#116744)
* [tools]some ui polish for build ipa validation * do not print out a few success validations * rename installed type to success for more general usage * forgot nit after reverting custom validation types and re-use doctor types
This commit is contained in:
parent
c98978ae36
commit
0916375f44
@ -42,21 +42,23 @@ Future<void> main() async {
|
||||
throw TaskResult.failure('Usage archive event not sent');
|
||||
}
|
||||
|
||||
if (!output.contains('Warning: App icon is using the wrong size (e.g. Icon-App-20x20@1x.png).')) {
|
||||
throw TaskResult.failure('Must validate incorrect app icon image size.');
|
||||
}
|
||||
|
||||
// The project is still using Flutter template icon and launch image.
|
||||
if (!output.contains('Warning: App icon is set to the default placeholder icon. Replace with unique icons.')) {
|
||||
throw TaskResult.failure('Must validate template app icon.');
|
||||
}
|
||||
if (!output.contains('Warning: Launch image is set to the default placeholder. Replace with unique launch images.')) {
|
||||
throw TaskResult.failure('Must validate template launch image.');
|
||||
}
|
||||
|
||||
// The project is still using com.example as bundle identifier prefix.
|
||||
if (!output.contains('Warning: Your application still contains the default "com.example" bundle identifier.')) {
|
||||
throw TaskResult.failure('Must validate the default bundle identifier prefix');
|
||||
// The output contains extra time related prefix, so cannot use a single string.
|
||||
const List<String> expectedValidationMessages = <String>[
|
||||
'[!] App Settings Validation\n',
|
||||
' • Version Number: 1.0.0\n',
|
||||
' • Build Number: 1\n',
|
||||
' • Display Name: Hello\n',
|
||||
' • Deployment Target: 11.0\n',
|
||||
' • Bundle Identifier: com.example.hello\n',
|
||||
' ! Your application still contains the default "com.example" bundle identifier.\n',
|
||||
'[!] App Icon and Launch Image Assets Validation\n',
|
||||
' ! App icon is set to the default placeholder icon. Replace with unique icons.\n',
|
||||
' ! App icon is using the incorrect size (e.g. Icon-App-20x20@1x.png).\n',
|
||||
' ! Launch image is set to the default placeholder icon. Replace with unique launch image.\n',
|
||||
'To update the settings, please refer to https://docs.flutter.dev/deployment/ios\n',
|
||||
];
|
||||
if (expectedValidationMessages.any((String message) => !output.contains(message))) {
|
||||
throw TaskResult.failure('Must have the expected validation message');
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -73,7 +73,7 @@ class AndroidStudioValidator extends DoctorValidator {
|
||||
if (_studio.isValid) {
|
||||
type = _hasIssues(messages)
|
||||
? ValidationType.partial
|
||||
: ValidationType.installed;
|
||||
: ValidationType.success;
|
||||
messages.addAll(_studio.validationMessages.map<ValidationMessage>(
|
||||
(String m) => ValidationMessage(m),
|
||||
));
|
||||
|
@ -258,7 +258,7 @@ class AndroidValidator extends DoctorValidator {
|
||||
}
|
||||
|
||||
// Success.
|
||||
return ValidationResult(ValidationType.installed, messages, statusInfo: sdkVersionText);
|
||||
return ValidationResult(ValidationType.success, messages, statusInfo: sdkVersionText);
|
||||
}
|
||||
}
|
||||
|
||||
@ -327,7 +327,7 @@ class AndroidLicenseValidator extends DoctorValidator {
|
||||
messages.add(ValidationMessage.error(_userMessages.androidLicensesUnknown(_platform)));
|
||||
return ValidationResult(ValidationType.partial, messages, statusInfo: sdkVersionText);
|
||||
}
|
||||
return ValidationResult(ValidationType.installed, messages, statusInfo: sdkVersionText);
|
||||
return ValidationResult(ValidationType.success, messages, statusInfo: sdkVersionText);
|
||||
}
|
||||
|
||||
Future<bool> _checkJavaVersionNoOutput() async {
|
||||
|
@ -15,6 +15,7 @@ import '../base/process.dart';
|
||||
import '../base/utils.dart';
|
||||
import '../build_info.dart';
|
||||
import '../convert.dart';
|
||||
import '../doctor_validator.dart';
|
||||
import '../globals.dart' as globals;
|
||||
import '../ios/application_package.dart';
|
||||
import '../ios/mac.dart';
|
||||
@ -277,7 +278,27 @@ class BuildIOSArchiveCommand extends _BuildIOSSubCommand {
|
||||
.toList();
|
||||
}
|
||||
|
||||
Future<void> _validateIconAssetsAfterArchive(StringBuffer messageBuffer) async {
|
||||
ValidationResult? _createValidationResult(String title, List<ValidationMessage> messages) {
|
||||
if (messages.isEmpty) {
|
||||
return null;
|
||||
}
|
||||
final bool anyInvalid = messages.any((ValidationMessage message) => message.type != ValidationMessageType.information);
|
||||
return ValidationResult(
|
||||
anyInvalid ? ValidationType.partial : ValidationType.success,
|
||||
messages,
|
||||
statusInfo: title,
|
||||
);
|
||||
}
|
||||
|
||||
ValidationMessage _createValidationMessage({
|
||||
required bool isValid,
|
||||
required String message,
|
||||
}) {
|
||||
// Use "information" type for valid message, and "hint" type for invalid message.
|
||||
return isValid ? ValidationMessage(message) : ValidationMessage.hint(message);
|
||||
}
|
||||
|
||||
Future<List<ValidationMessage>> _validateIconAssetsAfterArchive() async {
|
||||
final BuildableIOSApp app = await buildableIOSApp;
|
||||
|
||||
final Map<_ImageAssetFileKey, String> templateInfoMap = _parseImageAssetContentsJson(
|
||||
@ -287,24 +308,35 @@ class BuildIOSArchiveCommand extends _BuildIOSSubCommand {
|
||||
app.projectAppIconDirName,
|
||||
requiresSize: true);
|
||||
|
||||
final List<ValidationMessage> validationMessages = <ValidationMessage>[];
|
||||
|
||||
final bool usesTemplate = _isAssetStillUsingTemplateFiles(
|
||||
templateImageInfoMap: templateInfoMap,
|
||||
projectImageInfoMap: projectInfoMap,
|
||||
templateImageDirName: await app.templateAppIconDirNameForImages,
|
||||
projectImageDirName: app.projectAppIconDirName);
|
||||
|
||||
if (usesTemplate) {
|
||||
messageBuffer.writeln('\nWarning: App icon is set to the default placeholder icon. Replace with unique icons.');
|
||||
validationMessages.add(_createValidationMessage(
|
||||
isValid: false,
|
||||
message: 'App icon is set to the default placeholder icon. Replace with unique icons.',
|
||||
));
|
||||
}
|
||||
|
||||
final List<String> filesWithWrongSize = _imageFilesWithWrongSize(
|
||||
imageInfoMap: projectInfoMap,
|
||||
imageDirName: app.projectAppIconDirName);
|
||||
|
||||
if (filesWithWrongSize.isNotEmpty) {
|
||||
messageBuffer.writeln('\nWarning: App icon is using the wrong size (e.g. ${filesWithWrongSize.first}).');
|
||||
validationMessages.add(_createValidationMessage(
|
||||
isValid: false,
|
||||
message: 'App icon is using the incorrect size (e.g. ${filesWithWrongSize.first}).',
|
||||
));
|
||||
}
|
||||
return validationMessages;
|
||||
}
|
||||
|
||||
Future<void> _validateLaunchImageAssetsAfterArchive(StringBuffer messageBuffer) async {
|
||||
Future<List<ValidationMessage>> _validateLaunchImageAssetsAfterArchive() async {
|
||||
final BuildableIOSApp app = await buildableIOSApp;
|
||||
|
||||
final Map<_ImageAssetFileKey, String> templateInfoMap = _parseImageAssetContentsJson(
|
||||
@ -314,6 +346,8 @@ class BuildIOSArchiveCommand extends _BuildIOSSubCommand {
|
||||
app.projectLaunchImageDirName,
|
||||
requiresSize: false);
|
||||
|
||||
final List<ValidationMessage> validationMessages = <ValidationMessage>[];
|
||||
|
||||
final bool usesTemplate = _isAssetStillUsingTemplateFiles(
|
||||
templateImageInfoMap: templateInfoMap,
|
||||
projectImageInfoMap: projectInfoMap,
|
||||
@ -321,18 +355,23 @@ class BuildIOSArchiveCommand extends _BuildIOSSubCommand {
|
||||
projectImageDirName: app.projectLaunchImageDirName);
|
||||
|
||||
if (usesTemplate) {
|
||||
messageBuffer.writeln('\nWarning: Launch image is set to the default placeholder. Replace with unique launch images.');
|
||||
validationMessages.add(_createValidationMessage(
|
||||
isValid: false,
|
||||
message: 'Launch image is set to the default placeholder icon. Replace with unique launch image.',
|
||||
));
|
||||
}
|
||||
|
||||
return validationMessages;
|
||||
}
|
||||
|
||||
Future<void> _validateXcodeBuildSettingsAfterArchive(StringBuffer messageBuffer) async {
|
||||
Future<List<ValidationMessage>> _validateXcodeBuildSettingsAfterArchive() async {
|
||||
final BuildableIOSApp app = await buildableIOSApp;
|
||||
|
||||
final String plistPath = app.builtInfoPlistPathAfterArchive;
|
||||
|
||||
if (!globals.fs.file(plistPath).existsSync()) {
|
||||
globals.printError('Invalid iOS archive. Does not contain Info.plist.');
|
||||
return;
|
||||
return <ValidationMessage>[];
|
||||
}
|
||||
|
||||
final Map<String, String?> xcodeProjectSettingsMap = <String, String?>{};
|
||||
@ -343,17 +382,32 @@ class BuildIOSArchiveCommand extends _BuildIOSSubCommand {
|
||||
xcodeProjectSettingsMap['Deployment Target'] = globals.plistParser.getStringValueFromFile(plistPath, PlistParser.kMinimumOSVersionKey);
|
||||
xcodeProjectSettingsMap['Bundle Identifier'] = globals.plistParser.getStringValueFromFile(plistPath, PlistParser.kCFBundleIdentifierKey);
|
||||
|
||||
xcodeProjectSettingsMap.forEach((String title, String? info) {
|
||||
messageBuffer.writeln('$title: ${info ?? "Missing"}');
|
||||
});
|
||||
final List<ValidationMessage> validationMessages = xcodeProjectSettingsMap.entries.map((MapEntry<String, String?> entry) {
|
||||
final String title = entry.key;
|
||||
final String? info = entry.value;
|
||||
return _createValidationMessage(
|
||||
isValid: info != null,
|
||||
message: '$title: ${info ?? "Missing"}',
|
||||
);
|
||||
}).toList();
|
||||
|
||||
if (xcodeProjectSettingsMap.values.any((String? element) => element == null)) {
|
||||
messageBuffer.writeln('\nYou must set up the missing settings.');
|
||||
final bool hasMissingSettings = xcodeProjectSettingsMap.values.any((String? element) => element == null);
|
||||
if (hasMissingSettings) {
|
||||
validationMessages.add(_createValidationMessage(
|
||||
isValid: false,
|
||||
message: 'You must set up the missing app settings.'),
|
||||
);
|
||||
}
|
||||
|
||||
if (xcodeProjectSettingsMap['Bundle Identifier']?.startsWith('com.example') ?? false) {
|
||||
messageBuffer.writeln('\nWarning: Your application still contains the default "com.example" bundle identifier.');
|
||||
final bool usesDefaultBundleIdentifier = xcodeProjectSettingsMap['Bundle Identifier']?.startsWith('com.example') ?? false;
|
||||
if (usesDefaultBundleIdentifier) {
|
||||
validationMessages.add(_createValidationMessage(
|
||||
isValid: false,
|
||||
message: 'Your application still contains the default "com.example" bundle identifier.'),
|
||||
);
|
||||
}
|
||||
|
||||
return validationMessages;
|
||||
}
|
||||
|
||||
@override
|
||||
@ -362,13 +416,26 @@ class BuildIOSArchiveCommand extends _BuildIOSSubCommand {
|
||||
displayNullSafetyMode(buildInfo);
|
||||
final FlutterCommandResult xcarchiveResult = await super.runCommand();
|
||||
|
||||
final StringBuffer validationMessageBuffer = StringBuffer();
|
||||
await _validateXcodeBuildSettingsAfterArchive(validationMessageBuffer);
|
||||
await _validateIconAssetsAfterArchive(validationMessageBuffer);
|
||||
await _validateLaunchImageAssetsAfterArchive(validationMessageBuffer);
|
||||
final List<ValidationResult?> validationResults = <ValidationResult?>[];
|
||||
validationResults.add(_createValidationResult(
|
||||
'App Settings Validation',
|
||||
await _validateXcodeBuildSettingsAfterArchive(),
|
||||
));
|
||||
validationResults.add(_createValidationResult(
|
||||
'App Icon and Launch Image Assets Validation',
|
||||
await _validateIconAssetsAfterArchive() + await _validateLaunchImageAssetsAfterArchive(),
|
||||
));
|
||||
|
||||
validationMessageBuffer.write('\nTo update the settings, please refer to https://docs.flutter.dev/deployment/ios');
|
||||
globals.printBox(validationMessageBuffer.toString(), title: 'App Settings');
|
||||
for (final ValidationResult result in validationResults.whereType<ValidationResult>()) {
|
||||
globals.printStatus('\n${result.coloredLeadingBox} ${result.statusInfo}');
|
||||
for (final ValidationMessage message in result.messages) {
|
||||
globals.printStatus(
|
||||
'${message.coloredIndicator} ${message.message}',
|
||||
indent: result.leadingBox.length + 1,
|
||||
);
|
||||
}
|
||||
}
|
||||
globals.printStatus('\nTo update the settings, please refer to https://docs.flutter.dev/deployment/ios\n');
|
||||
|
||||
// xcarchive failed or not at expected location.
|
||||
if (xcarchiveResult.exitStatus != ExitStatus.success) {
|
||||
|
@ -303,7 +303,7 @@ class Doctor {
|
||||
case ValidationType.notAvailable:
|
||||
lineBuffer.write('is not available.');
|
||||
break;
|
||||
case ValidationType.installed:
|
||||
case ValidationType.success:
|
||||
lineBuffer.write('is fully installed.');
|
||||
break;
|
||||
}
|
||||
@ -320,7 +320,7 @@ class Doctor {
|
||||
));
|
||||
buffer.writeln();
|
||||
|
||||
if (result.type != ValidationType.installed) {
|
||||
if (result.type != ValidationType.success) {
|
||||
missingComponent = true;
|
||||
}
|
||||
}
|
||||
@ -400,7 +400,7 @@ class Doctor {
|
||||
case ValidationType.notAvailable:
|
||||
issues += 1;
|
||||
break;
|
||||
case ValidationType.installed:
|
||||
case ValidationType.success:
|
||||
break;
|
||||
}
|
||||
if (sendEvent) {
|
||||
@ -558,7 +558,7 @@ class FlutterValidator extends DoctorValidator {
|
||||
|
||||
ValidationType valid;
|
||||
if (messages.every((ValidationMessage message) => message.isInformation)) {
|
||||
valid = ValidationType.installed;
|
||||
valid = ValidationType.success;
|
||||
} else {
|
||||
// The issues for this validator stem from broken git configuration of the local install;
|
||||
// in that case, make it clear that it is fine to continue, but freshness check/upgrades
|
||||
@ -707,13 +707,13 @@ class DeviceValidator extends DoctorValidator {
|
||||
} else if (diagnostics.isNotEmpty) {
|
||||
installedMessages.addAll(diagnosticMessages);
|
||||
return ValidationResult(
|
||||
ValidationType.installed,
|
||||
ValidationType.success,
|
||||
installedMessages,
|
||||
statusInfo: _userMessages.devicesAvailable(devices.length)
|
||||
);
|
||||
} else {
|
||||
return ValidationResult(
|
||||
ValidationType.installed,
|
||||
ValidationType.success,
|
||||
installedMessages,
|
||||
statusInfo: _userMessages.devicesAvailable(devices.length)
|
||||
);
|
||||
|
@ -36,7 +36,7 @@ enum ValidationType {
|
||||
missing,
|
||||
partial,
|
||||
notAvailable,
|
||||
installed,
|
||||
success,
|
||||
}
|
||||
|
||||
enum ValidationMessageType {
|
||||
@ -116,7 +116,7 @@ class GroupedValidator extends DoctorValidator {
|
||||
for (final ValidationResult result in results) {
|
||||
statusInfo ??= result.statusInfo;
|
||||
switch (result.type) {
|
||||
case ValidationType.installed:
|
||||
case ValidationType.success:
|
||||
if (mergedType == ValidationType.missing) {
|
||||
mergedType = ValidationType.partial;
|
||||
}
|
||||
@ -127,7 +127,7 @@ class GroupedValidator extends DoctorValidator {
|
||||
break;
|
||||
case ValidationType.crash:
|
||||
case ValidationType.missing:
|
||||
if (mergedType == ValidationType.installed) {
|
||||
if (mergedType == ValidationType.success) {
|
||||
mergedType = ValidationType.partial;
|
||||
}
|
||||
break;
|
||||
@ -142,7 +142,7 @@ class GroupedValidator extends DoctorValidator {
|
||||
|
||||
@immutable
|
||||
class ValidationResult {
|
||||
/// [ValidationResult.type] should only equal [ValidationResult.installed]
|
||||
/// [ValidationResult.type] should only equal [ValidationResult.success]
|
||||
/// if no [messages] are hints or errors.
|
||||
const ValidationResult(this.type, this.messages, { this.statusInfo });
|
||||
|
||||
@ -171,7 +171,7 @@ class ValidationResult {
|
||||
return '[☠]';
|
||||
case ValidationType.missing:
|
||||
return '[✗]';
|
||||
case ValidationType.installed:
|
||||
case ValidationType.success:
|
||||
return '[✓]';
|
||||
case ValidationType.notAvailable:
|
||||
case ValidationType.partial:
|
||||
@ -186,7 +186,7 @@ class ValidationResult {
|
||||
return globals.terminal.color(leadingBox, TerminalColor.red);
|
||||
case ValidationType.missing:
|
||||
return globals.terminal.color(leadingBox, TerminalColor.red);
|
||||
case ValidationType.installed:
|
||||
case ValidationType.success:
|
||||
return globals.terminal.color(leadingBox, TerminalColor.green);
|
||||
case ValidationType.notAvailable:
|
||||
case ValidationType.partial:
|
||||
@ -202,7 +202,7 @@ class ValidationResult {
|
||||
return 'crash';
|
||||
case ValidationType.missing:
|
||||
return 'missing';
|
||||
case ValidationType.installed:
|
||||
case ValidationType.success:
|
||||
return 'installed';
|
||||
case ValidationType.notAvailable:
|
||||
return 'notAvailable';
|
||||
|
@ -110,7 +110,7 @@ class HttpHostValidator extends DoctorValidator {
|
||||
|
||||
if (availabilityResults.every((_HostValidationResult result) => result.available)) {
|
||||
return ValidationResult(
|
||||
ValidationType.installed,
|
||||
ValidationType.success,
|
||||
messages..add(const ValidationMessage('All required HTTP hosts are available')),
|
||||
);
|
||||
}
|
||||
|
@ -114,7 +114,7 @@ abstract class IntelliJValidator extends DoctorValidator {
|
||||
}
|
||||
|
||||
return ValidationResult(
|
||||
_hasIssues(messages) ? ValidationType.partial : ValidationType.installed,
|
||||
_hasIssues(messages) ? ValidationType.partial : ValidationType.success,
|
||||
messages,
|
||||
statusInfo: _userMessages.intellijStatusInfo(version),
|
||||
);
|
||||
|
@ -59,7 +59,7 @@ class LinuxDoctorValidator extends DoctorValidator {
|
||||
|
||||
@override
|
||||
Future<ValidationResult> validate() async {
|
||||
ValidationType validationType = ValidationType.installed;
|
||||
ValidationType validationType = ValidationType.success;
|
||||
final List<ValidationMessage> messages = <ValidationMessage>[];
|
||||
|
||||
final Map<String, _VersionInfo?> installedVersions = <String, _VersionInfo?>{
|
||||
|
@ -28,7 +28,7 @@ class CocoaPodsValidator extends DoctorValidator {
|
||||
final CocoaPodsStatus cocoaPodsStatus = await _cocoaPods
|
||||
.evaluateCocoaPodsInstallation;
|
||||
|
||||
ValidationType status = ValidationType.installed;
|
||||
ValidationType status = ValidationType.success;
|
||||
if (cocoaPodsStatus == CocoaPodsStatus.recommended) {
|
||||
messages.add(ValidationMessage(_userMessages.cocoaPodsVersion((await _cocoaPods.cocoaPodsVersionText).toString())));
|
||||
} else {
|
||||
|
@ -26,7 +26,7 @@ class XcodeValidator extends DoctorValidator {
|
||||
final String? xcodeSelectPath = _xcode.xcodeSelectPath;
|
||||
|
||||
if (_xcode.isInstalled) {
|
||||
xcodeStatus = ValidationType.installed;
|
||||
xcodeStatus = ValidationType.success;
|
||||
if (xcodeSelectPath != null) {
|
||||
messages.add(ValidationMessage(_userMessages.xcodeLocation(xcodeSelectPath)));
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ class ProxyValidator extends DoctorValidator {
|
||||
Future<ValidationResult> validate() async {
|
||||
if (_httpProxy.isEmpty) {
|
||||
return const ValidationResult(
|
||||
ValidationType.installed, <ValidationMessage>[]);
|
||||
ValidationType.success, <ValidationMessage>[]);
|
||||
}
|
||||
|
||||
final List<ValidationMessage> messages = <ValidationMessage>[
|
||||
@ -56,7 +56,7 @@ class ProxyValidator extends DoctorValidator {
|
||||
(ValidationMessage msg) => msg.isHint || msg.isError);
|
||||
|
||||
return ValidationResult(
|
||||
hasIssues ? ValidationType.partial : ValidationType.installed,
|
||||
hasIssues ? ValidationType.partial : ValidationType.success,
|
||||
messages,
|
||||
);
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ class VsCodeValidator extends DoctorValidator {
|
||||
: userMessages.vsCodeVersion(_vsCode.version.toString());
|
||||
|
||||
return ValidationResult(
|
||||
ValidationType.installed,
|
||||
ValidationType.success,
|
||||
_vsCode.validationMessages.toList(),
|
||||
statusInfo: vsCodeVersionText,
|
||||
);
|
||||
|
@ -39,7 +39,7 @@ abstract class ChromiumValidator extends DoctorValidator {
|
||||
);
|
||||
}
|
||||
return ValidationResult(
|
||||
ValidationType.installed,
|
||||
ValidationType.success,
|
||||
messages,
|
||||
);
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ class VisualStudioValidator extends DoctorValidator {
|
||||
String? versionInfo;
|
||||
|
||||
if (_visualStudio.isInstalled) {
|
||||
status = ValidationType.installed;
|
||||
status = ValidationType.success;
|
||||
|
||||
messages.add(ValidationMessage(
|
||||
_userMessages.visualStudioLocation(_visualStudio.installLocation ?? 'unknown')
|
||||
|
@ -53,7 +53,7 @@ class WindowsVersionValidator extends DoctorValidator {
|
||||
if (matches.length == 1 &&
|
||||
!kUnsupportedVersions
|
||||
.contains(matches.elementAt(0).group(3)?.split('.').elementAt(0))) {
|
||||
windowsVersionStatus = ValidationType.installed;
|
||||
windowsVersionStatus = ValidationType.success;
|
||||
statusInfo = 'Installed version of Windows is version 10 or higher';
|
||||
} else {
|
||||
windowsVersionStatus = ValidationType.missing;
|
||||
|
@ -918,18 +918,18 @@ void main() {
|
||||
expect(
|
||||
testLogger.statusText,
|
||||
contains(
|
||||
'┌─ App Settings ──────────────────────────────────────────────────────────────────┐\n'
|
||||
'│ Version Number: Missing │\n'
|
||||
'│ Build Number: Missing │\n'
|
||||
'│ Display Name: Missing │\n'
|
||||
'│ Deployment Target: Missing │\n'
|
||||
'│ Bundle Identifier: io.flutter.someProject │\n'
|
||||
'│ │\n'
|
||||
'│ You must set up the missing settings. │\n'
|
||||
'│ │\n'
|
||||
'│ To update the settings, please refer to https://docs.flutter.dev/deployment/ios │\n'
|
||||
'└─────────────────────────────────────────────────────────────────────────────────┘\n'
|
||||
'[!] App Settings Validation\n'
|
||||
' ! Version Number: Missing\n'
|
||||
' ! Build Number: Missing\n'
|
||||
' ! Display Name: Missing\n'
|
||||
' ! Deployment Target: Missing\n'
|
||||
' • Bundle Identifier: io.flutter.someProject\n'
|
||||
' ! You must set up the missing app settings.\n'
|
||||
));
|
||||
expect(
|
||||
testLogger.statusText,
|
||||
contains('To update the settings, please refer to https://docs.flutter.dev/deployment/ios')
|
||||
);
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => fileSystem,
|
||||
ProcessManager: () => fakeProcessManager,
|
||||
@ -972,17 +972,18 @@ void main() {
|
||||
expect(
|
||||
testLogger.statusText,
|
||||
contains(
|
||||
'┌─ App Settings ──────────────────────────────────────────────────────────────────┐\n'
|
||||
'│ Version Number: 12.34.56 │\n'
|
||||
'│ Build Number: 666 │\n'
|
||||
'│ Display Name: Awesome Gallery │\n'
|
||||
'│ Deployment Target: 11.0 │\n'
|
||||
'│ Bundle Identifier: io.flutter.someProject │\n'
|
||||
'│ │\n'
|
||||
'│ To update the settings, please refer to https://docs.flutter.dev/deployment/ios │\n'
|
||||
'└─────────────────────────────────────────────────────────────────────────────────┘\n'
|
||||
'[✓] App Settings Validation\n'
|
||||
' • Version Number: 12.34.56\n'
|
||||
' • Build Number: 666\n'
|
||||
' • Display Name: Awesome Gallery\n'
|
||||
' • Deployment Target: 11.0\n'
|
||||
' • Bundle Identifier: io.flutter.someProject\n'
|
||||
)
|
||||
);
|
||||
expect(
|
||||
testLogger.statusText,
|
||||
contains('To update the settings, please refer to https://docs.flutter.dev/deployment/ios')
|
||||
);
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => fileSystem,
|
||||
ProcessManager: () => fakeProcessManager,
|
||||
@ -1019,8 +1020,8 @@ void main() {
|
||||
<String>['build', 'ipa', '--no-pub']);
|
||||
|
||||
expect(
|
||||
testLogger.statusText,
|
||||
contains('Warning: Your application still contains the default "com.example" bundle identifier.')
|
||||
testLogger.statusText,
|
||||
contains(' ! Your application still contains the default "com.example" bundle identifier.')
|
||||
);
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => fileSystem,
|
||||
@ -1058,8 +1059,8 @@ void main() {
|
||||
<String>['build', 'ipa', '--no-pub']);
|
||||
|
||||
expect(
|
||||
testLogger.statusText,
|
||||
isNot(contains('Warning: Your application still contains the default "com.example" bundle identifier.'))
|
||||
testLogger.statusText,
|
||||
isNot(contains(' ! Your application still contains the default "com.example" bundle identifier.'))
|
||||
);
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => fileSystem,
|
||||
@ -1140,7 +1141,7 @@ void main() {
|
||||
|
||||
expect(
|
||||
testLogger.statusText,
|
||||
contains('Warning: App icon is set to the default placeholder icon. Replace with unique icons.'),
|
||||
contains(' ! App icon is set to the default placeholder icon. Replace with unique icons.'),
|
||||
);
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => fileSystem,
|
||||
@ -1217,7 +1218,10 @@ void main() {
|
||||
await createTestCommandRunner(command).run(
|
||||
<String>['build', 'ipa', '--no-pub']);
|
||||
|
||||
expect(testLogger.statusText, isNot(contains('Warning: App icon is set to the default placeholder icon. Replace with unique icons.')));
|
||||
expect(
|
||||
testLogger.statusText,
|
||||
isNot(contains(' ! App icon is set to the default placeholder icon. Replace with unique icons.'))
|
||||
);
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => fileSystem,
|
||||
ProcessManager: () => fakeProcessManager,
|
||||
@ -1273,7 +1277,10 @@ void main() {
|
||||
await createTestCommandRunner(command).run(
|
||||
<String>['build', 'ipa', '--no-pub']);
|
||||
|
||||
expect(testLogger.statusText, contains('Warning: App icon is using the wrong size (e.g. Icon-App-20x20@2x.png).'));
|
||||
expect(
|
||||
testLogger.statusText,
|
||||
contains(' ! App icon is using the incorrect size (e.g. Icon-App-20x20@2x.png).')
|
||||
);
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => fileSystem,
|
||||
ProcessManager: () => fakeProcessManager,
|
||||
@ -1329,7 +1336,10 @@ void main() {
|
||||
await createTestCommandRunner(command).run(
|
||||
<String>['build', 'ipa', '--no-pub']);
|
||||
|
||||
expect(testLogger.statusText, contains('Warning: App icon is using the wrong size (e.g. Icon-App-20x20@2x.png).'));
|
||||
expect(
|
||||
testLogger.statusText,
|
||||
contains(' ! App icon is using the incorrect size (e.g. Icon-App-20x20@2x.png).')
|
||||
);
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => fileSystem,
|
||||
ProcessManager: () => fakeProcessManager,
|
||||
@ -1385,7 +1395,10 @@ void main() {
|
||||
await createTestCommandRunner(command).run(
|
||||
<String>['build', 'ipa', '--no-pub']);
|
||||
|
||||
expect(testLogger.statusText, isNot(contains('Warning: App icon is using the wrong size (e.g. Icon-App-20x20@2x.png).')));
|
||||
expect(
|
||||
testLogger.statusText,
|
||||
isNot(contains(' ! App icon is using the incorrect size (e.g. Icon-App-20x20@2x.png).'))
|
||||
);
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => fileSystem,
|
||||
ProcessManager: () => fakeProcessManager,
|
||||
@ -1443,7 +1456,10 @@ void main() {
|
||||
<String>['build', 'ipa', '--no-pub']);
|
||||
|
||||
// The validation should be skipped, even when the icon size is incorrect.
|
||||
expect(testLogger.statusText, isNot(contains('Warning: App icon is using the wrong size (e.g. Icon-App-20x20@2x.png).')));
|
||||
expect(
|
||||
testLogger.statusText,
|
||||
isNot(contains(' ! App icon is using the incorrect size (e.g. Icon-App-20x20@2x.png).')),
|
||||
);
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => fileSystem,
|
||||
ProcessManager: () => fakeProcessManager,
|
||||
@ -1545,8 +1561,10 @@ void main() {
|
||||
|
||||
// The validation should be skipped, even when the image size is incorrect.
|
||||
for (final String imageFileName in imageFileNames) {
|
||||
expect(testLogger.statusText, isNot(contains(
|
||||
'Warning: App icon is using the wrong size (e.g. $imageFileName).')));
|
||||
expect(
|
||||
testLogger.statusText,
|
||||
isNot(contains(' ! App icon is using the incorrect size (e.g. $imageFileName).'))
|
||||
);
|
||||
}
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => fileSystem,
|
||||
@ -1623,7 +1641,7 @@ void main() {
|
||||
|
||||
expect(
|
||||
testLogger.statusText,
|
||||
contains('Warning: Launch image is set to the default placeholder. Replace with unique launch images.'),
|
||||
contains(' ! Launch image is set to the default placeholder icon. Replace with unique launch image.'),
|
||||
);
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => fileSystem,
|
||||
@ -1701,7 +1719,7 @@ void main() {
|
||||
|
||||
expect(
|
||||
testLogger.statusText,
|
||||
isNot(contains('Warning: Launch image is set to the default placeholder. Replace with unique launch images.')),
|
||||
isNot(contains(' ! Launch image is set to the default placeholder icon. Replace with unique launch image.')),
|
||||
);
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => fileSystem,
|
||||
|
@ -58,7 +58,7 @@ void main() {
|
||||
group('doctor', () {
|
||||
testUsingContext('vs code validator when both installed', () async {
|
||||
final ValidationResult result = await VsCodeValidatorTestTargets.installedWithExtension.validate();
|
||||
expect(result.type, ValidationType.installed);
|
||||
expect(result.type, ValidationType.success);
|
||||
expect(result.statusInfo, 'version 1.2.3');
|
||||
expect(result.messages, hasLength(2));
|
||||
|
||||
@ -85,7 +85,7 @@ void main() {
|
||||
testUsingContext('vs code validator when 64bit installed', () async {
|
||||
expect(VsCodeValidatorTestTargets.installedWithExtension64bit.title, 'VS Code, 64-bit edition');
|
||||
final ValidationResult result = await VsCodeValidatorTestTargets.installedWithExtension64bit.validate();
|
||||
expect(result.type, ValidationType.installed);
|
||||
expect(result.type, ValidationType.success);
|
||||
expect(result.statusInfo, 'version 1.2.3');
|
||||
expect(result.messages, hasLength(2));
|
||||
|
||||
@ -100,7 +100,7 @@ void main() {
|
||||
|
||||
testUsingContext('vs code validator when extension missing', () async {
|
||||
final ValidationResult result = await VsCodeValidatorTestTargets.installedWithoutExtension.validate();
|
||||
expect(result.type, ValidationType.installed);
|
||||
expect(result.type, ValidationType.success);
|
||||
expect(result.statusInfo, 'version 1.2.3');
|
||||
expect(result.messages, hasLength(2));
|
||||
|
||||
@ -157,7 +157,7 @@ void main() {
|
||||
userMessages: UserMessages(),
|
||||
);
|
||||
final ValidationResult result = await deviceValidator.validate();
|
||||
expect(result.type, ValidationType.installed);
|
||||
expect(result.type, ValidationType.success);
|
||||
expect(result.messages, const <ValidationMessage>[
|
||||
ValidationMessage('name (mobile) • device-id • android • 1.2.3'),
|
||||
ValidationMessage.hint('Device locked'),
|
||||
@ -850,7 +850,7 @@ class PassingValidator extends DoctorValidator {
|
||||
ValidationMessage('A helpful message'),
|
||||
ValidationMessage('A second, somewhat longer helpful message'),
|
||||
];
|
||||
return const ValidationResult(ValidationType.installed, messages, statusInfo: 'with statusInfo');
|
||||
return const ValidationResult(ValidationType.success, messages, statusInfo: 'with statusInfo');
|
||||
}
|
||||
}
|
||||
|
||||
@ -862,7 +862,7 @@ class PiiValidator extends DoctorValidator {
|
||||
const List<ValidationMessage> messages = <ValidationMessage>[
|
||||
ValidationMessage('Contains PII path/to/username', piiStrippedMessage: 'Does not contain PII'),
|
||||
];
|
||||
return const ValidationResult(ValidationType.installed, messages);
|
||||
return const ValidationResult(ValidationType.success, messages);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1089,7 +1089,7 @@ class PassingGroupedValidator extends DoctorValidator {
|
||||
const List<ValidationMessage> messages = <ValidationMessage>[
|
||||
ValidationMessage('A helpful message'),
|
||||
];
|
||||
return const ValidationResult(ValidationType.installed, messages);
|
||||
return const ValidationResult(ValidationType.success, messages);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1125,7 +1125,7 @@ class PassingGroupedValidatorWithStatus extends DoctorValidator {
|
||||
const List<ValidationMessage> messages = <ValidationMessage>[
|
||||
ValidationMessage('A different message'),
|
||||
];
|
||||
return const ValidationResult(ValidationType.installed, messages, statusInfo: 'A status message');
|
||||
return const ValidationResult(ValidationType.success, messages, statusInfo: 'A status message');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -41,8 +41,8 @@ void main() {
|
||||
// Run the validation check and get the results
|
||||
final ValidationResult result = await httpHostValidator.validate();
|
||||
|
||||
// Check for a ValidationType.installed result
|
||||
expect(result.type, equals(ValidationType.installed));
|
||||
// Check for a ValidationType.success result
|
||||
expect(result.type, equals(ValidationType.success));
|
||||
}
|
||||
});
|
||||
|
||||
@ -108,8 +108,8 @@ void main() {
|
||||
// Run the validation check and get the results
|
||||
final ValidationResult result = await httpHostValidator.validate();
|
||||
|
||||
// Check for a ValidationType.installed result
|
||||
expect(result.type, equals(ValidationType.installed));
|
||||
// Check for a ValidationType.success result
|
||||
expect(result.type, equals(ValidationType.success));
|
||||
}
|
||||
});
|
||||
|
||||
@ -253,8 +253,8 @@ void main() {
|
||||
// Run the validation check and get the results
|
||||
final ValidationResult result = await httpHostValidator.validate();
|
||||
|
||||
// Check for a ValidationType.installed result
|
||||
expect(result.type, equals(ValidationType.installed));
|
||||
// Check for a ValidationType.success result
|
||||
expect(result.type, equals(ValidationType.success));
|
||||
}
|
||||
});
|
||||
|
||||
@ -275,8 +275,8 @@ void main() {
|
||||
// Run the validation check and get the results
|
||||
final ValidationResult result = await httpHostValidator.validate();
|
||||
|
||||
// Check for a ValidationType.installed result
|
||||
expect(result.type, equals(ValidationType.installed));
|
||||
// Check for a ValidationType.success result
|
||||
expect(result.type, equals(ValidationType.success));
|
||||
}
|
||||
});
|
||||
|
||||
@ -295,8 +295,8 @@ void main() {
|
||||
// Run the validation check and get the results
|
||||
final ValidationResult result = await httpHostValidator.validate();
|
||||
|
||||
// Check for a ValidationType.installed result
|
||||
expect(result.type, equals(ValidationType.installed));
|
||||
// Check for a ValidationType.success result
|
||||
expect(result.type, equals(ValidationType.success));
|
||||
}
|
||||
});
|
||||
});
|
||||
|
@ -142,7 +142,7 @@ void main() {
|
||||
// gen_snapshot is downloaded on demand, and the doctor should not
|
||||
// fail if the gen_snapshot binary is not present.
|
||||
expect(await flutterValidator.validate(), _matchDoctorValidation(
|
||||
validationType: ValidationType.installed,
|
||||
validationType: ValidationType.success,
|
||||
statusInfo: 'Channel beta, 1.0.0, on Windows, locale en_US.UTF-8',
|
||||
messages: anything,
|
||||
));
|
||||
@ -199,7 +199,7 @@ void main() {
|
||||
);
|
||||
|
||||
expect(await flutterValidator.validate(), _matchDoctorValidation(
|
||||
validationType: ValidationType.installed,
|
||||
validationType: ValidationType.success,
|
||||
statusInfo: 'Channel beta, 1.0.0, on Windows, locale en_US.UTF-8',
|
||||
messages: containsAll(const <ValidationMessage>[
|
||||
ValidationMessage('Pub download mirror https://example.com/pub'),
|
||||
@ -327,7 +327,7 @@ void main() {
|
||||
);
|
||||
|
||||
expect(await flutterValidator.validate(), _matchDoctorValidation(
|
||||
validationType: ValidationType.installed,
|
||||
validationType: ValidationType.success,
|
||||
statusInfo: 'Channel beta, 1.0.0, on Linux, locale en_US.UTF-8',
|
||||
messages: contains(const ValidationMessage('Upstream repository https://github.com/flutter/flutter.git')),
|
||||
));
|
||||
@ -418,7 +418,7 @@ void main() {
|
||||
);
|
||||
|
||||
expect(await flutterValidator.validate(), _matchDoctorValidation(
|
||||
validationType: ValidationType.installed,
|
||||
validationType: ValidationType.success,
|
||||
statusInfo: 'Channel beta, 1.0.0, on Linux, locale en_US.UTF-8',
|
||||
messages: isNot(
|
||||
contains(const ValidationMessage(
|
||||
@ -598,7 +598,7 @@ void main() {
|
||||
);
|
||||
|
||||
expect(await flutterValidator.validate(), _matchDoctorValidation(
|
||||
validationType: ValidationType.installed,
|
||||
validationType: ValidationType.success,
|
||||
statusInfo: 'Channel beta, 1.0.0, on Linux, locale en_US.UTF-8',
|
||||
messages: isNot(contains(isA<ValidationMessage>().having(
|
||||
(ValidationMessage message) => message.message,
|
||||
|
@ -77,7 +77,7 @@ void main() {
|
||||
);
|
||||
expect(1, installed.length);
|
||||
final ValidationResult result = await installed.toList()[0].validate();
|
||||
expect(ValidationType.installed, result.type);
|
||||
expect(ValidationType.success, result.type);
|
||||
});
|
||||
|
||||
testWithoutContext('intellij(2020.1) plugins check on linux (installed via JetBrains ToolBox app)', () async {
|
||||
@ -104,7 +104,7 @@ void main() {
|
||||
);
|
||||
expect(1, installed.length);
|
||||
final ValidationResult result = await installed.toList()[0].validate();
|
||||
expect(ValidationType.installed, result.type);
|
||||
expect(ValidationType.success, result.type);
|
||||
});
|
||||
|
||||
testWithoutContext('intellij(>=2020.2) plugins check on linux (installed via JetBrains ToolBox app)', () async {
|
||||
@ -131,7 +131,7 @@ void main() {
|
||||
);
|
||||
expect(1, installed.length);
|
||||
final ValidationResult result = await installed.toList()[0].validate();
|
||||
expect(ValidationType.installed, result.type);
|
||||
expect(ValidationType.success, result.type);
|
||||
});
|
||||
|
||||
testWithoutContext('intellij(2020.1~) plugins check on linux (installed via tar.gz)', () async {
|
||||
@ -158,7 +158,7 @@ void main() {
|
||||
);
|
||||
expect(1, installed.length);
|
||||
final ValidationResult result = await installed.toList()[0].validate();
|
||||
expect(ValidationType.installed, result.type);
|
||||
expect(ValidationType.success, result.type);
|
||||
});
|
||||
|
||||
testWithoutContext('legacy intellij(<2020) plugins check on windows', () async {
|
||||
@ -185,7 +185,7 @@ void main() {
|
||||
);
|
||||
expect(1, installed.length);
|
||||
final ValidationResult result = await installed.toList()[0].validate();
|
||||
expect(ValidationType.installed, result.type);
|
||||
expect(ValidationType.success, result.type);
|
||||
});
|
||||
|
||||
testWithoutContext('intellij(2020.1 ~ 2020.2) plugins check on windows (installed via JetBrains ToolBox app)', () async {
|
||||
@ -212,7 +212,7 @@ void main() {
|
||||
);
|
||||
expect(1, installed.length);
|
||||
final ValidationResult result = await installed.toList()[0].validate();
|
||||
expect(ValidationType.installed, result.type);
|
||||
expect(ValidationType.success, result.type);
|
||||
});
|
||||
|
||||
testWithoutContext('intellij(>=2020.3) plugins check on windows (installed via JetBrains ToolBox app and plugins)', () async {
|
||||
@ -239,7 +239,7 @@ void main() {
|
||||
);
|
||||
expect(1, installed.length);
|
||||
final ValidationResult result = await installed.toList()[0].validate();
|
||||
expect(ValidationType.installed, result.type);
|
||||
expect(ValidationType.success, result.type);
|
||||
});
|
||||
|
||||
testWithoutContext('intellij(2020.1~) plugins check on windows (installed via installer)', () async {
|
||||
@ -266,7 +266,7 @@ void main() {
|
||||
);
|
||||
expect(1, installed.length);
|
||||
final ValidationResult result = await installed.toList()[0].validate();
|
||||
expect(ValidationType.installed, result.type);
|
||||
expect(ValidationType.success, result.type);
|
||||
});
|
||||
|
||||
testWithoutContext('can locate installations on macOS from Spotlight', () {
|
||||
|
@ -114,7 +114,7 @@ void main() {
|
||||
);
|
||||
final ValidationResult result = await linuxDoctorValidator.validate();
|
||||
|
||||
expect(result.type, ValidationType.installed);
|
||||
expect(result.type, ValidationType.success);
|
||||
expect(result.messages, const <ValidationMessage>[
|
||||
ValidationMessage('clang version 4.0.1-6+build1'),
|
||||
ValidationMessage('cmake version 3.16.3'),
|
||||
|
@ -15,7 +15,7 @@ void main() {
|
||||
testWithoutContext('Emits installed status when CocoaPods is installed', () async {
|
||||
final CocoaPodsValidator workflow = CocoaPodsValidator(FakeCocoaPods(CocoaPodsStatus.recommended, '1000.0.0'), UserMessages());
|
||||
final ValidationResult result = await workflow.validate();
|
||||
expect(result.type, ValidationType.installed);
|
||||
expect(result.type, ValidationType.success);
|
||||
});
|
||||
|
||||
testWithoutContext('Emits missing status when CocoaPods is not installed', () async {
|
||||
|
@ -182,7 +182,7 @@ void main() {
|
||||
);
|
||||
final XcodeValidator validator = XcodeValidator(xcode: xcode, userMessages: UserMessages());
|
||||
final ValidationResult result = await validator.validate();
|
||||
expect(result.type, ValidationType.installed);
|
||||
expect(result.type, ValidationType.success);
|
||||
expect(result.messages.length, 2);
|
||||
final ValidationMessage firstMessage = result.messages.first;
|
||||
expect(firstMessage.type, ValidationMessageType.information);
|
||||
|
@ -50,7 +50,7 @@ void main() {
|
||||
testWithoutContext('WebValidator can find executable on macOS', () async {
|
||||
final ValidationResult result = await webValidator.validate();
|
||||
|
||||
expect(result.type, ValidationType.installed);
|
||||
expect(result.type, ValidationType.success);
|
||||
});
|
||||
|
||||
testWithoutContext('WebValidator Can notice missing macOS executable ', () async {
|
||||
|
@ -165,7 +165,7 @@ void main() {
|
||||
userMessages.visualStudioVersion(fakeVisualStudio.displayName!, fakeVisualStudio.fullVersion!));
|
||||
|
||||
expect(result.messages.contains(expectedDisplayNameMessage), true);
|
||||
expect(result.type, ValidationType.installed);
|
||||
expect(result.type, ValidationType.success);
|
||||
});
|
||||
|
||||
testWithoutContext('Emits missing status when Visual Studio is not installed', () async {
|
||||
|
@ -138,7 +138,7 @@ Hyper-V Requirements: A hypervisor has been detected. Features required for
|
||||
/// The expected validation result object for
|
||||
/// a passing windows version test
|
||||
const ValidationResult validWindows10ValidationResult = ValidationResult(
|
||||
ValidationType.installed,
|
||||
ValidationType.success,
|
||||
<ValidationMessage>[],
|
||||
statusInfo: 'Installed version of Windows is version 10 or higher',
|
||||
);
|
||||
|
Loading…
Reference in New Issue
Block a user