// Copyright 2014 The Flutter Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. import 'package:file/memory.dart'; import 'package:flutter_tools/src/base/file_system.dart'; import 'package:flutter_tools/src/base/logger.dart'; import 'package:flutter_tools/src/ios/migrations/ios_deployment_target_migration.dart'; import 'package:flutter_tools/src/project.dart'; import 'package:test/fake.dart'; import '../../src/common.dart'; void main() { group('IOSDeploymentTargetMigration', () { late MemoryFileSystem memoryFileSystem; late BufferLogger testLogger; late FakeIosProject mockIosProject; late File xcodeProjectInfoFile; late File podfile; late File appFrameworkInfoPlist; setUp(() { memoryFileSystem = MemoryFileSystem(); testLogger = BufferLogger.test(); mockIosProject = FakeIosProject(); xcodeProjectInfoFile = memoryFileSystem.file('project.pbxproj'); podfile = memoryFileSystem.file('Podfile'); appFrameworkInfoPlist = memoryFileSystem.file('AppFrameworkInfo.plist'); mockIosProject.xcodeProjectInfoFile = xcodeProjectInfoFile; mockIosProject.podfile = podfile; mockIosProject.appFrameworkInfoPlist = appFrameworkInfoPlist; }); testWithoutContext('skips migration if files do not exist', () async { final migration = IOSDeploymentTargetMigration(mockIosProject, testLogger); await migration.migrate(); expect(testLogger.traceText, contains('Xcode project not found')); expect(testLogger.traceText, contains('AppFrameworkInfo.plist not found')); expect(testLogger.traceText, contains('Podfile not found')); expect(xcodeProjectInfoFile.existsSync(), isFalse); expect(podfile.existsSync(), isFalse); expect(appFrameworkInfoPlist.existsSync(), isFalse); }); testWithoutContext('migrates project.pbxproj', () async { xcodeProjectInfoFile.writeAsStringSync(''' IPHONEOS_DEPLOYMENT_TARGET = 8.0; IPHONEOS_DEPLOYMENT_TARGET = 9.0; IPHONEOS_DEPLOYMENT_TARGET = 11.0; IPHONEOS_DEPLOYMENT_TARGET = 12.0; IPHONEOS_DEPLOYMENT_TARGET = 13.0; '''); final migration = IOSDeploymentTargetMigration(mockIosProject, testLogger); await migration.migrate(); expect(testLogger.statusText, contains('Updating minimum iOS deployment target to 13.0.')); expect(xcodeProjectInfoFile.readAsStringSync(), ''' IPHONEOS_DEPLOYMENT_TARGET = 13.0; IPHONEOS_DEPLOYMENT_TARGET = 13.0; IPHONEOS_DEPLOYMENT_TARGET = 13.0; IPHONEOS_DEPLOYMENT_TARGET = 13.0; IPHONEOS_DEPLOYMENT_TARGET = 13.0; '''); }); testWithoutContext('migrates Podfile', () async { podfile.writeAsStringSync(''' platform :ios, '9.0' platform :ios, '11.0' platform :ios, '12.0' platform :ios, '13.0' '''); final migration = IOSDeploymentTargetMigration(mockIosProject, testLogger); await migration.migrate(); expect(testLogger.statusText, contains('Updating minimum iOS deployment target to 13.0.')); expect(podfile.readAsStringSync(), ''' platform :ios, '13.0' platform :ios, '13.0' platform :ios, '13.0' platform :ios, '13.0' '''); }); testWithoutContext('migrates AppFrameworkInfo.plist', () async { appFrameworkInfoPlist.writeAsStringSync(''' MinimumOSVersion 8.0 MinimumOSVersion 9.0 MinimumOSVersion 11.0 MinimumOSVersion 12.0 MinimumOSVersion 13.0 '''); final migration = IOSDeploymentTargetMigration(mockIosProject, testLogger); await migration.migrate(); // It should remove the keys entirely expect(appFrameworkInfoPlist.readAsStringSync(), ''' '''); }); testWithoutContext('does not migrate if already up to date', () async { xcodeProjectInfoFile.writeAsStringSync('IPHONEOS_DEPLOYMENT_TARGET = 14.0;'); podfile.writeAsStringSync("platform :ios, '14.0'"); appFrameworkInfoPlist.writeAsStringSync(''' MinimumOSVersion 14.0 '''); final migration = IOSDeploymentTargetMigration(mockIosProject, testLogger); await migration.migrate(); expect(testLogger.statusText, isEmpty); expect(xcodeProjectInfoFile.readAsStringSync(), 'IPHONEOS_DEPLOYMENT_TARGET = 14.0;'); expect(podfile.readAsStringSync(), "platform :ios, '14.0'"); expect(appFrameworkInfoPlist.readAsStringSync(), ''' MinimumOSVersion 14.0 '''); }); }); } class FakeIosProject extends Fake implements IosProject { @override late File xcodeProjectInfoFile; @override late File podfile; @override late File appFrameworkInfoPlist; }