Unverified Commit 7c75c01f authored by Jenn Magder's avatar Jenn Magder Committed by GitHub

Add recommended Xcode version to doctor (#73808)

parent c65304bb
......@@ -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;
}
if (majorVersion == kXcodeRequiredVersionMajor) {
if (minorVersion == kXcodeRequiredVersionMinor) {
return patchVersion >= kXcodeRequiredVersionPatch;
}
return minorVersion >= kXcodeRequiredVersionMinor;
return currentVersion >= xcodeRequiredVersion;
}
bool get isRecommendedVersionSatisfactory {
if (!_xcodeProjectInterpreter.isInstalled) {
return false;
}
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());
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment