mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
Add recommended Xcode version to doctor (#73808)
This commit is contained in:
parent
c65304bbf1
commit
7c75c01fc3
@ -139,8 +139,9 @@ class UserMessages {
|
||||
|
||||
// Messages used in XcodeValidator
|
||||
String xcodeLocation(String location) => 'Xcode at $location';
|
||||
String xcodeOutdated(int versionMajor, int versionMinor, int versionPatch) =>
|
||||
'Flutter requires a minimum Xcode version of $versionMajor.$versionMinor.$versionPatch.\n'
|
||||
|
||||
String xcodeOutdated(String currentVersion, String recommendedVersion) =>
|
||||
'Xcode $currentVersion out of date ($recommendedVersion is recommended).\n'
|
||||
'Download the latest version or update via the Mac App Store.';
|
||||
String get xcodeEula => "Xcode end user license agreement not signed; open Xcode or run the command 'sudo xcodebuild -license'.";
|
||||
String get xcodeMissingSimct =>
|
||||
|
@ -637,7 +637,7 @@ class XcodeBuildExecution {
|
||||
final Map<String, String> buildSettings;
|
||||
}
|
||||
|
||||
const String _xcodeRequirement = 'Xcode $kXcodeRequiredVersionMajor.$kXcodeRequiredVersionMinor.$kXcodeRequiredVersionPatch or greater is required to develop for iOS.';
|
||||
final String _xcodeRequirement = 'Xcode $xcodeRequiredVersion or greater is required to develop for iOS.';
|
||||
|
||||
bool _checkXcodeVersion() {
|
||||
if (!globals.platform.isMacOS) {
|
||||
@ -647,7 +647,7 @@ bool _checkXcodeVersion() {
|
||||
globals.printError('Cannot find "xcodebuild". $_xcodeRequirement');
|
||||
return false;
|
||||
}
|
||||
if (!globals.xcode.isVersionSatisfactory) {
|
||||
if (!globals.xcode.isRequiredVersionSatisfactory) {
|
||||
globals.printError('Found "${globals.xcodeProjectInterpreter.versionText}". $_xcodeRequirement');
|
||||
return false;
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ import '../../base/common.dart';
|
||||
import '../../base/file_system.dart';
|
||||
import '../../base/logger.dart';
|
||||
import '../../base/project_migrator.dart';
|
||||
import '../../base/version.dart';
|
||||
import '../../macos/xcode.dart';
|
||||
import '../../project.dart';
|
||||
import '../../reporting/reporting.dart';
|
||||
@ -99,7 +100,7 @@ class RemoveFrameworkLinkAndEmbeddingMigration extends ProjectMigrator {
|
||||
if (line.contains('/* App.framework ') || line.contains('/* Flutter.framework ')) {
|
||||
// Print scary message if the user is on Xcode 11.4 or greater, or if Xcode isn't installed.
|
||||
final bool xcodeIsInstalled = _xcode.isInstalled;
|
||||
if(!xcodeIsInstalled || (_xcode.majorVersion > 11 || (_xcode.majorVersion == 11 && _xcode.minorVersion >= 4))) {
|
||||
if(!xcodeIsInstalled || _xcode.currentVersion >= Version(11, 4, 0)) {
|
||||
UsageEvent('ios-migration', 'remove-frameworks', label: 'failure', flutterUsage: _usage).send();
|
||||
throwToolExit('Your Xcode project requires migration. See https://flutter.dev/docs/development/ios-project-migration for details.');
|
||||
}
|
||||
|
@ -73,7 +73,6 @@ class IOSSimulatorUtils {
|
||||
name: device.name,
|
||||
simControl: _simControl,
|
||||
simulatorCategory: device.category,
|
||||
xcode: _xcode,
|
||||
);
|
||||
}).toList();
|
||||
}
|
||||
@ -309,9 +308,7 @@ class IOSSimulator extends Device {
|
||||
this.name,
|
||||
this.simulatorCategory,
|
||||
@required SimControl simControl,
|
||||
@required Xcode xcode,
|
||||
}) : _simControl = simControl,
|
||||
_xcode = xcode,
|
||||
super(
|
||||
id,
|
||||
category: Category.mobile,
|
||||
@ -325,7 +322,6 @@ class IOSSimulator extends Device {
|
||||
final String simulatorCategory;
|
||||
|
||||
final SimControl _simControl;
|
||||
final Xcode _xcode;
|
||||
|
||||
@override
|
||||
DevFSWriter createDevFSWriter(covariant ApplicationPackage app, String userIdentifier) {
|
||||
@ -610,12 +606,8 @@ class IOSSimulator extends Device {
|
||||
}
|
||||
}
|
||||
|
||||
bool get _xcodeVersionSupportsScreenshot {
|
||||
return _xcode.majorVersion > 8 || (_xcode.majorVersion == 8 && _xcode.minorVersion >= 2);
|
||||
}
|
||||
|
||||
@override
|
||||
bool get supportsScreenshot => _xcodeVersionSupportsScreenshot;
|
||||
bool get supportsScreenshot => true;
|
||||
|
||||
@override
|
||||
Future<void> takeScreenshot(File outputFile) {
|
||||
|
@ -14,6 +14,7 @@ import '../base/io.dart';
|
||||
import '../base/logger.dart';
|
||||
import '../base/platform.dart';
|
||||
import '../base/process.dart';
|
||||
import '../base/version.dart';
|
||||
import '../build_info.dart';
|
||||
import '../cache.dart';
|
||||
import '../convert.dart';
|
||||
@ -25,9 +26,8 @@ import '../ios/mac.dart';
|
||||
import '../ios/xcodeproj.dart';
|
||||
import '../reporting/reporting.dart';
|
||||
|
||||
const int kXcodeRequiredVersionMajor = 11;
|
||||
const int kXcodeRequiredVersionMinor = 0;
|
||||
const int kXcodeRequiredVersionPatch = 0;
|
||||
Version get xcodeRequiredVersion => Version(11, 0, 0, text: '11.0');
|
||||
Version get xcodeRecommendedVersion => Version(12, 0, 1, text: '12.0.1');
|
||||
|
||||
/// SDK name passed to `xcrun --sdk`. Corresponds to undocumented Xcode
|
||||
/// SUPPORTED_PLATFORMS values.
|
||||
@ -60,7 +60,7 @@ class Xcode {
|
||||
final FileSystem _fileSystem;
|
||||
final XcodeProjectInterpreter _xcodeProjectInterpreter;
|
||||
|
||||
bool get isInstalledAndMeetsVersionCheck => _platform.isMacOS && isInstalled && isVersionSatisfactory;
|
||||
bool get isInstalledAndMeetsVersionCheck => _platform.isMacOS && isInstalled && isRequiredVersionSatisfactory;
|
||||
|
||||
String _xcodeSelectPath;
|
||||
String get xcodeSelectPath {
|
||||
@ -85,9 +85,13 @@ class Xcode {
|
||||
return _xcodeProjectInterpreter.isInstalled;
|
||||
}
|
||||
|
||||
int get majorVersion => _xcodeProjectInterpreter.majorVersion;
|
||||
int get minorVersion => _xcodeProjectInterpreter.minorVersion;
|
||||
int get patchVersion => _xcodeProjectInterpreter.patchVersion;
|
||||
Version get currentVersion => Version(
|
||||
_xcodeProjectInterpreter.majorVersion,
|
||||
_xcodeProjectInterpreter.minorVersion,
|
||||
_xcodeProjectInterpreter.patchVersion,
|
||||
text:
|
||||
'${_xcodeProjectInterpreter.majorVersion}.${_xcodeProjectInterpreter.minorVersion}.${_xcodeProjectInterpreter.patchVersion}',
|
||||
);
|
||||
|
||||
String get versionText => _xcodeProjectInterpreter.versionText;
|
||||
|
||||
@ -132,20 +136,18 @@ class Xcode {
|
||||
return _isSimctlInstalled;
|
||||
}
|
||||
|
||||
bool get isVersionSatisfactory {
|
||||
bool get isRequiredVersionSatisfactory {
|
||||
if (!_xcodeProjectInterpreter.isInstalled) {
|
||||
return false;
|
||||
}
|
||||
if (majorVersion > kXcodeRequiredVersionMajor) {
|
||||
return true;
|
||||
return currentVersion >= xcodeRequiredVersion;
|
||||
}
|
||||
|
||||
bool get isRecommendedVersionSatisfactory {
|
||||
if (!_xcodeProjectInterpreter.isInstalled) {
|
||||
return false;
|
||||
}
|
||||
if (majorVersion == kXcodeRequiredVersionMajor) {
|
||||
if (minorVersion == kXcodeRequiredVersionMinor) {
|
||||
return patchVersion >= kXcodeRequiredVersionPatch;
|
||||
}
|
||||
return minorVersion >= kXcodeRequiredVersionMinor;
|
||||
}
|
||||
return false;
|
||||
return currentVersion >= xcodeRecommendedVersion;
|
||||
}
|
||||
|
||||
/// See [XcodeProjectInterpreter.xcrunCommand].
|
||||
|
@ -29,18 +29,20 @@ class XcodeValidator extends DoctorValidator {
|
||||
xcodeStatus = ValidationType.installed;
|
||||
|
||||
messages.add(ValidationMessage(_userMessages.xcodeLocation(_xcode.xcodeSelectPath)));
|
||||
|
||||
xcodeVersionInfo = _xcode.versionText;
|
||||
if (xcodeVersionInfo.contains(',')) {
|
||||
xcodeVersionInfo = xcodeVersionInfo.substring(0, xcodeVersionInfo.indexOf(','));
|
||||
}
|
||||
messages.add(ValidationMessage(_xcode.versionText));
|
||||
|
||||
if (!_xcode.isInstalledAndMeetsVersionCheck) {
|
||||
xcodeStatus = ValidationType.partial;
|
||||
messages.add(ValidationMessage.error(
|
||||
_userMessages.xcodeOutdated(kXcodeRequiredVersionMajor, kXcodeRequiredVersionMinor, kXcodeRequiredVersionPatch)
|
||||
));
|
||||
messages.add(ValidationMessage.error(_userMessages.xcodeOutdated(
|
||||
_xcode.currentVersion.toString(),
|
||||
xcodeRecommendedVersion.toString(),
|
||||
)));
|
||||
} else if (!_xcode.isRecommendedVersionSatisfactory) {
|
||||
xcodeStatus = ValidationType.partial;
|
||||
messages.add(ValidationMessage.hint(_userMessages.xcodeOutdated(
|
||||
_xcode.currentVersion.toString(),
|
||||
xcodeRecommendedVersion.toString(),
|
||||
)));
|
||||
}
|
||||
|
||||
if (!_xcode.eulaSigned) {
|
||||
|
@ -101,7 +101,7 @@ void main() {
|
||||
}
|
||||
);
|
||||
mockXcode = MockXcode();
|
||||
when(mockXcode.isVersionSatisfactory).thenReturn(true);
|
||||
when(mockXcode.isRequiredVersionSatisfactory).thenReturn(true);
|
||||
when(mockXcode.xcrunCommand()).thenReturn(<String>['xcrun']);
|
||||
fileSystem.file('foo/.packages')
|
||||
..createSync(recursive: true)
|
||||
|
@ -6,6 +6,7 @@ import 'package:file/file.dart';
|
||||
import 'package:file/memory.dart';
|
||||
import 'package:flutter_tools/src/base/logger.dart';
|
||||
import 'package:flutter_tools/src/base/project_migrator.dart';
|
||||
import 'package:flutter_tools/src/base/version.dart';
|
||||
import 'package:flutter_tools/src/ios/migrations/project_base_configuration_migration.dart';
|
||||
import 'package:flutter_tools/src/ios/migrations/project_build_location_migration.dart';
|
||||
import 'package:flutter_tools/src/ios/migrations/remove_framework_link_and_embedding_migration.dart';
|
||||
@ -145,8 +146,7 @@ keep this 2
|
||||
746232531E83B71900CC1A5E /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 746232521E83B71900CC1A5E /* App.framework */; };
|
||||
''');
|
||||
when(mockXcode.isInstalled).thenReturn(true);
|
||||
when(mockXcode.majorVersion).thenReturn(11);
|
||||
when(mockXcode.minorVersion).thenReturn(4);
|
||||
when(mockXcode.currentVersion).thenReturn(Version(11, 4, 0));
|
||||
|
||||
final RemoveFrameworkLinkAndEmbeddingMigration iosProjectMigration = RemoveFrameworkLinkAndEmbeddingMigration(
|
||||
mockIosProject,
|
||||
@ -164,8 +164,7 @@ keep this 2
|
||||
9705A1C71CF904A300538480 /* Flutter.framework in Embed Frameworks */,
|
||||
''');
|
||||
when(mockXcode.isInstalled).thenReturn(true);
|
||||
when(mockXcode.majorVersion).thenReturn(11);
|
||||
when(mockXcode.minorVersion).thenReturn(4);
|
||||
when(mockXcode.currentVersion).thenReturn(Version(11, 4, 0));
|
||||
|
||||
final RemoveFrameworkLinkAndEmbeddingMigration iosProjectMigration = RemoveFrameworkLinkAndEmbeddingMigration(
|
||||
mockIosProject,
|
||||
@ -198,8 +197,7 @@ keep this 2
|
||||
746232531E83B71900CC1A5E /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 746232521E83B71900CC1A5E /* App.framework */; };
|
||||
''');
|
||||
when(mockXcode.isInstalled).thenReturn(true);
|
||||
when(mockXcode.majorVersion).thenReturn(11);
|
||||
when(mockXcode.minorVersion).thenReturn(3);
|
||||
when(mockXcode.currentVersion).thenReturn(Version(11, 3, 0));
|
||||
|
||||
final RemoveFrameworkLinkAndEmbeddingMigration iosProjectMigration = RemoveFrameworkLinkAndEmbeddingMigration(
|
||||
mockIosProject,
|
||||
@ -217,8 +215,7 @@ keep this 2
|
||||
746232531E83B71900CC1A5E /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 746232521E83B71900CC1A5E /* App.framework */; };
|
||||
''');
|
||||
when(mockXcode.isInstalled).thenReturn(true);
|
||||
when(mockXcode.majorVersion).thenReturn(11);
|
||||
when(mockXcode.minorVersion).thenReturn(4);
|
||||
when(mockXcode.currentVersion).thenReturn(Version(11, 4, 0));
|
||||
|
||||
final RemoveFrameworkLinkAndEmbeddingMigration iosProjectMigration = RemoveFrameworkLinkAndEmbeddingMigration(
|
||||
mockIosProject,
|
||||
@ -235,8 +232,7 @@ keep this 2
|
||||
746232531E83B71900CC1A5E /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 746232521E83B71900CC1A5E /* App.framework */; };
|
||||
''');
|
||||
when(mockXcode.isInstalled).thenReturn(true);
|
||||
when(mockXcode.majorVersion).thenReturn(12);
|
||||
when(mockXcode.minorVersion).thenReturn(0);
|
||||
when(mockXcode.currentVersion).thenReturn(Version(12, 0, 0));
|
||||
|
||||
final RemoveFrameworkLinkAndEmbeddingMigration iosProjectMigration = RemoveFrameworkLinkAndEmbeddingMigration(
|
||||
mockIosProject,
|
||||
|
@ -70,7 +70,6 @@ void main() {
|
||||
final IOSSimulator simulator = IOSSimulator(
|
||||
'123',
|
||||
simControl: mockSimControl,
|
||||
xcode: mockXcode,
|
||||
);
|
||||
final DevicePortForwarder portForwarder = simulator.portForwarder;
|
||||
await portForwarder.forward(123);
|
||||
@ -94,7 +93,6 @@ void main() {
|
||||
final IOSSimulator simulator = IOSSimulator(
|
||||
'123',
|
||||
simControl: MockSimControl(),
|
||||
xcode: MockXcode(),
|
||||
);
|
||||
|
||||
expect(simulator.supportsRuntimeMode(BuildMode.debug), true);
|
||||
@ -109,11 +107,9 @@ void main() {
|
||||
|
||||
group('logFilePath', () {
|
||||
MockSimControl mockSimControl;
|
||||
MockXcode mockXcode;
|
||||
|
||||
setUp(() {
|
||||
mockSimControl = MockSimControl();
|
||||
mockXcode = MockXcode();
|
||||
});
|
||||
|
||||
testUsingContext('defaults to rooted from HOME', () {
|
||||
@ -121,7 +117,6 @@ void main() {
|
||||
final IOSSimulator simulator = IOSSimulator(
|
||||
'123',
|
||||
simControl: mockSimControl,
|
||||
xcode: mockXcode,
|
||||
);
|
||||
expect(simulator.logFilePath, '/foo/bar/Library/Logs/CoreSimulator/123/system.log');
|
||||
}, overrides: <Type, Generator>{
|
||||
@ -129,7 +124,6 @@ void main() {
|
||||
FileSystemUtils: () => fsUtils,
|
||||
FileSystem: () => fileSystem,
|
||||
ProcessManager: () => FakeProcessManager.any(),
|
||||
Xcode: () => mockXcode,
|
||||
}, testOn: 'posix');
|
||||
|
||||
testUsingContext('respects IOS_SIMULATOR_LOG_FILE_PATH', () {
|
||||
@ -138,7 +132,6 @@ void main() {
|
||||
final IOSSimulator simulator = IOSSimulator(
|
||||
'456',
|
||||
simControl: mockSimControl,
|
||||
xcode: mockXcode,
|
||||
);
|
||||
expect(simulator.logFilePath, '/baz/qux/456/system.log');
|
||||
}, overrides: <Type, Generator>{
|
||||
@ -146,7 +139,6 @@ void main() {
|
||||
FileSystemUtils: () => fsUtils,
|
||||
FileSystem: () => fileSystem,
|
||||
ProcessManager: () => FakeProcessManager.any(),
|
||||
Xcode: () => mockXcode,
|
||||
});
|
||||
});
|
||||
|
||||
@ -201,11 +193,9 @@ void main() {
|
||||
|
||||
group('sdkMajorVersion', () {
|
||||
MockSimControl mockSimControl;
|
||||
MockXcode mockXcode;
|
||||
|
||||
setUp(() {
|
||||
mockSimControl = MockSimControl();
|
||||
mockXcode = MockXcode();
|
||||
});
|
||||
|
||||
// This new version string appears in SimulatorApp-850 CoreSimulator-518.16 beta.
|
||||
@ -215,7 +205,6 @@ void main() {
|
||||
name: 'iPhone SE',
|
||||
simulatorCategory: 'com.apple.CoreSimulator.SimRuntime.iOS-11-3',
|
||||
simControl: mockSimControl,
|
||||
xcode: mockXcode,
|
||||
);
|
||||
|
||||
expect(await device.sdkMajorVersion, 11);
|
||||
@ -227,7 +216,6 @@ void main() {
|
||||
name: 'iPhone SE',
|
||||
simulatorCategory: 'iOS 11.2',
|
||||
simControl: mockSimControl,
|
||||
xcode: mockXcode,
|
||||
);
|
||||
|
||||
expect(await device.sdkMajorVersion, 11);
|
||||
@ -239,7 +227,6 @@ void main() {
|
||||
name: 'iPhone SE',
|
||||
simulatorCategory: 'iOS 11.2',
|
||||
simControl: mockSimControl,
|
||||
xcode: mockXcode,
|
||||
);
|
||||
|
||||
expect(device.category, Category.mobile);
|
||||
@ -248,11 +235,9 @@ void main() {
|
||||
|
||||
group('IOSSimulator.isSupported', () {
|
||||
MockSimControl mockSimControl;
|
||||
MockXcode mockXcode;
|
||||
|
||||
setUp(() {
|
||||
mockSimControl = MockSimControl();
|
||||
mockXcode = MockXcode();
|
||||
});
|
||||
|
||||
testUsingContext('Apple TV is unsupported', () {
|
||||
@ -260,14 +245,12 @@ void main() {
|
||||
'x',
|
||||
name: 'Apple TV',
|
||||
simControl: mockSimControl,
|
||||
xcode: mockXcode,
|
||||
);
|
||||
expect(simulator.isSupported(), false);
|
||||
}, overrides: <Type, Generator>{
|
||||
Platform: () => osx,
|
||||
FileSystem: () => fileSystem,
|
||||
ProcessManager: () => FakeProcessManager.any(),
|
||||
Xcode: () => mockXcode,
|
||||
});
|
||||
|
||||
testUsingContext('Apple Watch is unsupported', () {
|
||||
@ -275,13 +258,11 @@ void main() {
|
||||
'x',
|
||||
name: 'Apple Watch',
|
||||
simControl: mockSimControl,
|
||||
xcode: mockXcode,
|
||||
).isSupported(), false);
|
||||
}, overrides: <Type, Generator>{
|
||||
Platform: () => osx,
|
||||
FileSystem: () => fileSystem,
|
||||
ProcessManager: () => FakeProcessManager.any(),
|
||||
Xcode: () => mockXcode,
|
||||
});
|
||||
|
||||
testUsingContext('iPad 2 is supported', () {
|
||||
@ -289,13 +270,11 @@ void main() {
|
||||
'x',
|
||||
name: 'iPad 2',
|
||||
simControl: mockSimControl,
|
||||
xcode: mockXcode,
|
||||
).isSupported(), true);
|
||||
}, overrides: <Type, Generator>{
|
||||
Platform: () => osx,
|
||||
FileSystem: () => fileSystem,
|
||||
ProcessManager: () => FakeProcessManager.any(),
|
||||
Xcode: () => mockXcode,
|
||||
});
|
||||
|
||||
testUsingContext('iPad Retina is supported', () {
|
||||
@ -303,13 +282,11 @@ void main() {
|
||||
'x',
|
||||
name: 'iPad Retina',
|
||||
simControl: mockSimControl,
|
||||
xcode: mockXcode,
|
||||
).isSupported(), true);
|
||||
}, overrides: <Type, Generator>{
|
||||
Platform: () => osx,
|
||||
FileSystem: () => fileSystem,
|
||||
ProcessManager: () => FakeProcessManager.any(),
|
||||
Xcode: () => mockXcode,
|
||||
});
|
||||
|
||||
testUsingContext('iPhone 5 is supported', () {
|
||||
@ -317,13 +294,11 @@ void main() {
|
||||
'x',
|
||||
name: 'iPhone 5',
|
||||
simControl: mockSimControl,
|
||||
xcode: mockXcode,
|
||||
).isSupported(), true);
|
||||
}, overrides: <Type, Generator>{
|
||||
Platform: () => osx,
|
||||
FileSystem: () => fileSystem,
|
||||
ProcessManager: () => FakeProcessManager.any(),
|
||||
Xcode: () => mockXcode,
|
||||
});
|
||||
|
||||
testUsingContext('iPhone 5s is supported', () {
|
||||
@ -331,13 +306,11 @@ void main() {
|
||||
'x',
|
||||
name: 'iPhone 5s',
|
||||
simControl: mockSimControl,
|
||||
xcode: mockXcode,
|
||||
).isSupported(), true);
|
||||
}, overrides: <Type, Generator>{
|
||||
Platform: () => osx,
|
||||
FileSystem: () => fileSystem,
|
||||
ProcessManager: () => FakeProcessManager.any(),
|
||||
Xcode: () => mockXcode,
|
||||
});
|
||||
|
||||
testUsingContext('iPhone SE is supported', () {
|
||||
@ -345,13 +318,11 @@ void main() {
|
||||
'x',
|
||||
name: 'iPhone SE',
|
||||
simControl: mockSimControl,
|
||||
xcode: mockXcode,
|
||||
).isSupported(), true);
|
||||
}, overrides: <Type, Generator>{
|
||||
Platform: () => osx,
|
||||
FileSystem: () => fileSystem,
|
||||
ProcessManager: () => FakeProcessManager.any(),
|
||||
Xcode: () => mockXcode,
|
||||
});
|
||||
|
||||
testUsingContext('iPhone 7 Plus is supported', () {
|
||||
@ -359,13 +330,11 @@ void main() {
|
||||
'x',
|
||||
name: 'iPhone 7 Plus',
|
||||
simControl: mockSimControl,
|
||||
xcode: mockXcode,
|
||||
).isSupported(), true);
|
||||
}, overrides: <Type, Generator>{
|
||||
Platform: () => osx,
|
||||
FileSystem: () => fileSystem,
|
||||
ProcessManager: () => FakeProcessManager.any(),
|
||||
Xcode: () => mockXcode,
|
||||
});
|
||||
|
||||
testUsingContext('iPhone X is supported', () {
|
||||
@ -373,13 +342,11 @@ void main() {
|
||||
'x',
|
||||
name: 'iPhone X',
|
||||
simControl: mockSimControl,
|
||||
xcode: mockXcode,
|
||||
).isSupported(), true);
|
||||
}, overrides: <Type, Generator>{
|
||||
Platform: () => osx,
|
||||
FileSystem: () => fileSystem,
|
||||
ProcessManager: () => FakeProcessManager.any(),
|
||||
Xcode: () => mockXcode,
|
||||
});
|
||||
});
|
||||
|
||||
@ -410,26 +377,14 @@ void main() {
|
||||
'x',
|
||||
name: 'iPhone SE',
|
||||
simControl: simControl,
|
||||
xcode: mockXcode,
|
||||
);
|
||||
when(mockXcode.xcrunCommand()).thenReturn(<String>['xcrun']);
|
||||
});
|
||||
|
||||
testWithoutContext(
|
||||
"old Xcode doesn't support screenshot",
|
||||
() {
|
||||
when(mockXcode.majorVersion).thenReturn(7);
|
||||
when(mockXcode.minorVersion).thenReturn(1);
|
||||
expect(deviceUnderTest.supportsScreenshot, false);
|
||||
},
|
||||
);
|
||||
|
||||
testWithoutContext(
|
||||
'Xcode 8.2+ supports screenshots',
|
||||
'supports screenshots',
|
||||
() async {
|
||||
when(mockXcode.majorVersion).thenReturn(8);
|
||||
when(mockXcode.minorVersion).thenReturn(2);
|
||||
expect(deviceUnderTest.supportsScreenshot, true);
|
||||
final File screenshot = MemoryFileSystem.test().file('screenshot.png');
|
||||
await deviceUnderTest.takeScreenshot(screenshot);
|
||||
verify(mockProcessManager.run(
|
||||
@ -468,7 +423,6 @@ void main() {
|
||||
name: 'iPhone SE',
|
||||
simulatorCategory: 'iOS 9.3',
|
||||
simControl: mockSimControl,
|
||||
xcode: mockXcode,
|
||||
);
|
||||
await launchDeviceSystemLogTool(device);
|
||||
expect(
|
||||
@ -484,7 +438,6 @@ void main() {
|
||||
fileSystem: fileSystem,
|
||||
platform: macosPlatform,
|
||||
),
|
||||
Xcode: () => mockXcode,
|
||||
});
|
||||
|
||||
testUsingContext('unified logging with app name', () async {
|
||||
@ -493,7 +446,6 @@ void main() {
|
||||
name: 'iPhone SE',
|
||||
simulatorCategory: 'iOS 11.0',
|
||||
simControl: mockSimControl,
|
||||
xcode: mockXcode,
|
||||
);
|
||||
await launchDeviceUnifiedLogging(device, 'My Super Awesome App');
|
||||
|
||||
@ -530,7 +482,6 @@ void main() {
|
||||
name: 'iPhone SE',
|
||||
simulatorCategory: 'iOS 11.0',
|
||||
simControl: mockSimControl,
|
||||
xcode: mockXcode,
|
||||
);
|
||||
await launchDeviceUnifiedLogging(device, null);
|
||||
|
||||
@ -557,7 +508,6 @@ void main() {
|
||||
overrides: <Type, Generator>{
|
||||
ProcessManager: () => mockProcessManager,
|
||||
FileSystem: () => fileSystem,
|
||||
Xcode: () => mockXcode,
|
||||
});
|
||||
});
|
||||
|
||||
@ -597,7 +547,6 @@ Dec 20 17:04:32 md32-11-vm1 Another App[88374]: Ignore this text'''
|
||||
'123456',
|
||||
simulatorCategory: 'iOS 10.0',
|
||||
simControl: mockSimControl,
|
||||
xcode: mockXcode,
|
||||
);
|
||||
final DeviceLogReader logReader = device.getLogReader(
|
||||
app: await BuildableIOSApp.fromProject(mockIosProject, null),
|
||||
@ -632,7 +581,6 @@ Dec 20 17:04:32 md32-11-vm1 Another App[88374]: Ignore this text'''
|
||||
'123456',
|
||||
simulatorCategory: 'iOS 10.3',
|
||||
simControl: mockSimControl,
|
||||
xcode: mockXcode,
|
||||
);
|
||||
final DeviceLogReader logReader = device.getLogReader(
|
||||
app: await BuildableIOSApp.fromProject(mockIosProject, null),
|
||||
@ -680,7 +628,6 @@ Dec 20 17:04:32 md32-11-vm1 Another App[88374]: Ignore this text'''
|
||||
'123456',
|
||||
simulatorCategory: 'iOS 10.3',
|
||||
simControl: mockSimControl,
|
||||
xcode: mockXcode,
|
||||
);
|
||||
final DeviceLogReader logReader = device.getLogReader(
|
||||
app: await BuildableIOSApp.fromProject(mockIosProject, null),
|
||||
@ -746,7 +693,6 @@ Dec 20 17:04:32 md32-11-vm1 Another App[88374]: Ignore this text'''
|
||||
'123456',
|
||||
simulatorCategory: 'iOS 11.0',
|
||||
simControl: mockSimControl,
|
||||
xcode: mockXcode,
|
||||
);
|
||||
final DeviceLogReader logReader = device.getLogReader(
|
||||
app: await BuildableIOSApp.fromProject(mockIosProject, null),
|
||||
@ -761,7 +707,6 @@ Dec 20 17:04:32 md32-11-vm1 Another App[88374]: Ignore this text'''
|
||||
}, overrides: <Type, Generator>{
|
||||
ProcessManager: () => fakeProcessManager,
|
||||
FileSystem: () => fileSystem,
|
||||
Xcode: () => mockXcode,
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -864,7 +809,6 @@ Dec 20 17:04:32 md32-11-vm1 Another App[88374]: Ignore this text'''
|
||||
name: 'Testo',
|
||||
simulatorCategory: 'NaN',
|
||||
simControl: simControl,
|
||||
xcode: mockXcode,
|
||||
);
|
||||
|
||||
expect(await iosSimulatorA.sdkMajorVersion, 11);
|
||||
@ -923,7 +867,6 @@ Dec 20 17:04:32 md32-11-vm1 Another App[88374]: Ignore this text'''
|
||||
name: 'iPhone SE',
|
||||
simulatorCategory: 'iOS 11.2',
|
||||
simControl: simControl,
|
||||
xcode: mockXcode,
|
||||
);
|
||||
when(globals.plistParser.getValueFromFile(any, any)).thenReturn('correct');
|
||||
|
||||
@ -948,7 +891,6 @@ Dec 20 17:04:32 md32-11-vm1 Another App[88374]: Ignore this text'''
|
||||
name: 'iPhone SE',
|
||||
simulatorCategory: 'iOS 11.2',
|
||||
simControl: simControl,
|
||||
xcode: mockXcode,
|
||||
);
|
||||
|
||||
final Directory mockDir = globals.fs.currentDirectory;
|
||||
@ -991,7 +933,6 @@ flutter:
|
||||
final IOSSimulator simulator = IOSSimulator(
|
||||
'test',
|
||||
simControl: mockSimControl,
|
||||
xcode: mockXcode,
|
||||
);
|
||||
expect(simulator.isSupportedForProject(flutterProject), true);
|
||||
}, overrides: <Type, Generator>{
|
||||
@ -1010,7 +951,6 @@ flutter:
|
||||
final IOSSimulator simulator = IOSSimulator(
|
||||
'test',
|
||||
simControl: mockSimControl,
|
||||
xcode: mockXcode,
|
||||
);
|
||||
expect(simulator.isSupportedForProject(flutterProject), true);
|
||||
}, overrides: <Type, Generator>{
|
||||
@ -1027,7 +967,6 @@ flutter:
|
||||
final IOSSimulator simulator = IOSSimulator(
|
||||
'test',
|
||||
simControl: mockSimControl,
|
||||
xcode: mockXcode,
|
||||
);
|
||||
expect(simulator.isSupportedForProject(flutterProject), false);
|
||||
}, overrides: <Type, Generator>{
|
||||
@ -1040,7 +979,6 @@ flutter:
|
||||
final IOSSimulator simulator = IOSSimulator(
|
||||
'test',
|
||||
simControl: mockSimControl,
|
||||
xcode: mockXcode,
|
||||
);
|
||||
|
||||
expect(simulator.createDevFSWriter(null, ''), isA<LocalDevFSWriter>());
|
||||
|
@ -221,13 +221,13 @@ void main() {
|
||||
when(mockXcodeProjectInterpreter.minorVersion).thenReturn(0);
|
||||
when(mockXcodeProjectInterpreter.patchVersion).thenReturn(0);
|
||||
|
||||
expect(xcode.isVersionSatisfactory, isFalse);
|
||||
expect(xcode.isRequiredVersionSatisfactory, isFalse);
|
||||
});
|
||||
|
||||
testWithoutContext('xcodeVersionSatisfactory is false when xcodebuild tools are not installed', () {
|
||||
when(mockXcodeProjectInterpreter.isInstalled).thenReturn(false);
|
||||
|
||||
expect(xcode.isVersionSatisfactory, isFalse);
|
||||
expect(xcode.isRequiredVersionSatisfactory, isFalse);
|
||||
});
|
||||
|
||||
testWithoutContext('xcodeVersionSatisfactory is true when version meets minimum', () {
|
||||
@ -236,7 +236,7 @@ void main() {
|
||||
when(mockXcodeProjectInterpreter.minorVersion).thenReturn(0);
|
||||
when(mockXcodeProjectInterpreter.patchVersion).thenReturn(0);
|
||||
|
||||
expect(xcode.isVersionSatisfactory, isTrue);
|
||||
expect(xcode.isRequiredVersionSatisfactory, isTrue);
|
||||
});
|
||||
|
||||
testWithoutContext('xcodeVersionSatisfactory is true when major version exceeds minimum', () {
|
||||
@ -245,7 +245,7 @@ void main() {
|
||||
when(mockXcodeProjectInterpreter.minorVersion).thenReturn(0);
|
||||
when(mockXcodeProjectInterpreter.patchVersion).thenReturn(0);
|
||||
|
||||
expect(xcode.isVersionSatisfactory, isTrue);
|
||||
expect(xcode.isRequiredVersionSatisfactory, isTrue);
|
||||
});
|
||||
|
||||
testWithoutContext('xcodeVersionSatisfactory is true when minor version exceeds minimum', () {
|
||||
@ -254,7 +254,7 @@ void main() {
|
||||
when(mockXcodeProjectInterpreter.minorVersion).thenReturn(3);
|
||||
when(mockXcodeProjectInterpreter.patchVersion).thenReturn(0);
|
||||
|
||||
expect(xcode.isVersionSatisfactory, isTrue);
|
||||
expect(xcode.isRequiredVersionSatisfactory, isTrue);
|
||||
});
|
||||
|
||||
testWithoutContext('xcodeVersionSatisfactory is true when patch version exceeds minimum', () {
|
||||
@ -263,7 +263,58 @@ void main() {
|
||||
when(mockXcodeProjectInterpreter.minorVersion).thenReturn(0);
|
||||
when(mockXcodeProjectInterpreter.patchVersion).thenReturn(1);
|
||||
|
||||
expect(xcode.isVersionSatisfactory, isTrue);
|
||||
expect(xcode.isRequiredVersionSatisfactory, isTrue);
|
||||
});
|
||||
|
||||
testWithoutContext('isRecommendedVersionSatisfactory is false when version is less than minimum', () {
|
||||
when(mockXcodeProjectInterpreter.isInstalled).thenReturn(true);
|
||||
when(mockXcodeProjectInterpreter.majorVersion).thenReturn(9);
|
||||
when(mockXcodeProjectInterpreter.minorVersion).thenReturn(0);
|
||||
when(mockXcodeProjectInterpreter.patchVersion).thenReturn(0);
|
||||
|
||||
expect(xcode.isRecommendedVersionSatisfactory, isFalse);
|
||||
});
|
||||
|
||||
testWithoutContext('isRecommendedVersionSatisfactory is false when xcodebuild tools are not installed', () {
|
||||
when(mockXcodeProjectInterpreter.isInstalled).thenReturn(false);
|
||||
|
||||
expect(xcode.isRecommendedVersionSatisfactory, isFalse);
|
||||
});
|
||||
|
||||
testWithoutContext('isRecommendedVersionSatisfactory is true when version meets minimum', () {
|
||||
when(mockXcodeProjectInterpreter.isInstalled).thenReturn(true);
|
||||
when(mockXcodeProjectInterpreter.majorVersion).thenReturn(12);
|
||||
when(mockXcodeProjectInterpreter.minorVersion).thenReturn(0);
|
||||
when(mockXcodeProjectInterpreter.patchVersion).thenReturn(1);
|
||||
|
||||
expect(xcode.isRecommendedVersionSatisfactory, isTrue);
|
||||
});
|
||||
|
||||
testWithoutContext('isRecommendedVersionSatisfactory is true when major version exceeds minimum', () {
|
||||
when(mockXcodeProjectInterpreter.isInstalled).thenReturn(true);
|
||||
when(mockXcodeProjectInterpreter.majorVersion).thenReturn(13);
|
||||
when(mockXcodeProjectInterpreter.minorVersion).thenReturn(0);
|
||||
when(mockXcodeProjectInterpreter.patchVersion).thenReturn(0);
|
||||
|
||||
expect(xcode.isRecommendedVersionSatisfactory, isTrue);
|
||||
});
|
||||
|
||||
testWithoutContext('isRecommendedVersionSatisfactory is true when minor version exceeds minimum', () {
|
||||
when(mockXcodeProjectInterpreter.isInstalled).thenReturn(true);
|
||||
when(mockXcodeProjectInterpreter.majorVersion).thenReturn(12);
|
||||
when(mockXcodeProjectInterpreter.minorVersion).thenReturn(3);
|
||||
when(mockXcodeProjectInterpreter.patchVersion).thenReturn(0);
|
||||
|
||||
expect(xcode.isRecommendedVersionSatisfactory, isTrue);
|
||||
});
|
||||
|
||||
testWithoutContext('isRecommendedVersionSatisfactory is true when patch version exceeds minimum', () {
|
||||
when(mockXcodeProjectInterpreter.isInstalled).thenReturn(true);
|
||||
when(mockXcodeProjectInterpreter.majorVersion).thenReturn(12);
|
||||
when(mockXcodeProjectInterpreter.minorVersion).thenReturn(0);
|
||||
when(mockXcodeProjectInterpreter.patchVersion).thenReturn(2);
|
||||
|
||||
expect(xcode.isRecommendedVersionSatisfactory, isTrue);
|
||||
});
|
||||
|
||||
testWithoutContext('isInstalledAndMeetsVersionCheck is false when not installed', () {
|
||||
|
@ -3,6 +3,7 @@
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:flutter_tools/src/base/user_messages.dart';
|
||||
import 'package:flutter_tools/src/base/version.dart';
|
||||
import 'package:flutter_tools/src/doctor.dart';
|
||||
import 'package:flutter_tools/src/macos/xcode.dart';
|
||||
import 'package:flutter_tools/src/macos/xcode_validator.dart';
|
||||
@ -40,12 +41,32 @@ void main() {
|
||||
when(xcode.isInstalled).thenReturn(true);
|
||||
when(xcode.versionText)
|
||||
.thenReturn('Xcode 7.0.1\nBuild version 7C1002\n');
|
||||
when(xcode.currentVersion).thenReturn(Version(7, 0, 1));
|
||||
when(xcode.isInstalledAndMeetsVersionCheck).thenReturn(false);
|
||||
when(xcode.isRecommendedVersionSatisfactory).thenReturn(false);
|
||||
when(xcode.eulaSigned).thenReturn(true);
|
||||
when(xcode.isSimctlInstalled).thenReturn(true);
|
||||
final XcodeValidator validator = XcodeValidator(xcode: xcode, userMessages: UserMessages());
|
||||
final ValidationResult result = await validator.validate();
|
||||
expect(result.type, ValidationType.partial);
|
||||
expect(result.messages.last.type, ValidationMessageType.error);
|
||||
expect(result.messages.last.message, contains('Xcode 7.0.1 out of date (12.0.1 is recommended)'));
|
||||
});
|
||||
|
||||
testWithoutContext('Emits partial status when Xcode below recommended version', () async {
|
||||
when(xcode.isInstalled).thenReturn(true);
|
||||
when(xcode.versionText)
|
||||
.thenReturn('Xcode 11.0\nBuild version 11A420a\n');
|
||||
when(xcode.currentVersion).thenReturn(Version(11, 0, 0));
|
||||
when(xcode.isInstalledAndMeetsVersionCheck).thenReturn(true);
|
||||
when(xcode.isRecommendedVersionSatisfactory).thenReturn(false);
|
||||
when(xcode.eulaSigned).thenReturn(true);
|
||||
when(xcode.isSimctlInstalled).thenReturn(true);
|
||||
final XcodeValidator validator = XcodeValidator(xcode: xcode, userMessages: UserMessages());
|
||||
final ValidationResult result = await validator.validate();
|
||||
expect(result.type, ValidationType.partial);
|
||||
expect(result.messages.last.type, ValidationMessageType.hint);
|
||||
expect(result.messages.last.message, contains('Xcode 11.0.0 out of date (12.0.1 is recommended)'));
|
||||
});
|
||||
|
||||
testWithoutContext('Emits partial status when Xcode EULA not signed', () async {
|
||||
@ -53,6 +74,7 @@ void main() {
|
||||
when(xcode.versionText)
|
||||
.thenReturn('Xcode 8.2.1\nBuild version 8C1002\n');
|
||||
when(xcode.isInstalledAndMeetsVersionCheck).thenReturn(true);
|
||||
when(xcode.isRecommendedVersionSatisfactory).thenReturn(true);
|
||||
when(xcode.eulaSigned).thenReturn(false);
|
||||
when(xcode.isSimctlInstalled).thenReturn(true);
|
||||
final XcodeValidator validator = XcodeValidator(xcode: xcode, userMessages: UserMessages());
|
||||
@ -65,6 +87,7 @@ void main() {
|
||||
when(xcode.versionText)
|
||||
.thenReturn('Xcode 8.2.1\nBuild version 8C1002\n');
|
||||
when(xcode.isInstalledAndMeetsVersionCheck).thenReturn(true);
|
||||
when(xcode.isRecommendedVersionSatisfactory).thenReturn(true);
|
||||
when(xcode.eulaSigned).thenReturn(true);
|
||||
when(xcode.isSimctlInstalled).thenReturn(false);
|
||||
final XcodeValidator validator = XcodeValidator(xcode: xcode, userMessages: UserMessages());
|
||||
@ -78,6 +101,7 @@ void main() {
|
||||
when(xcode.versionText)
|
||||
.thenReturn('Xcode 8.2.1\nBuild version 8C1002\n');
|
||||
when(xcode.isInstalledAndMeetsVersionCheck).thenReturn(true);
|
||||
when(xcode.isRecommendedVersionSatisfactory).thenReturn(true);
|
||||
when(xcode.eulaSigned).thenReturn(true);
|
||||
when(xcode.isSimctlInstalled).thenReturn(true);
|
||||
final XcodeValidator validator = XcodeValidator(xcode: xcode, userMessages: UserMessages());
|
||||
|
Loading…
Reference in New Issue
Block a user