Commit 6a49419b authored by xster's avatar xster Committed by GitHub

Create Podfile dynamically part 1 (#11101)

* start

* with create

* refactor cocoapod code, add tests

* fix tests

* throw when cocoapod missing

* obj-c projects don’t use use_framework!
parent 0adb39ae
......@@ -224,6 +224,9 @@ class BuildableIOSApp extends IOSApp {
@override
String get deviceBundlePath => _buildAppPath('iphoneos');
/// True if the app is built from a Swift project. Null if unknown.
bool get isSwift => buildSettings?.containsKey('SWIFT_VERSION');
String _buildAppPath(String type) {
return fs.path.join(getIosBuildDirectory(), 'Release-$type', kBundleName);
}
......
// Copyright 2017 The Chromium 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 'dart:async';
import 'package:meta/meta.dart';
import '../base/common.dart';
import '../base/context.dart';
import '../base/file_system.dart';
import '../base/io.dart';
import '../base/logger.dart';
import '../base/process.dart';
import '../base/process_manager.dart';
import '../base/version.dart';
import '../cache.dart';
import '../globals.dart';
final String noCocoaPodsConsequence = '''
CocoaPods is used to retrieve the iOS platform side's plugin code that responds to your plugin usage on the Dart side.
Without resolving iOS dependencies with CocoaPods, plugins will not work on iOS.
For more info, see https://flutter.io/platform-plugins''';
final String cocoaPodsInstallInstructions = '''
brew update
brew install cocoapods
pod setup''';
final String cocoaPodsUpgradeInstructions = '''
brew update
brew upgrade cocoapods
pod setup''';
CocoaPods get cocoaPods => context.putIfAbsent(CocoaPods, () => const CocoaPods());
class CocoaPods {
const CocoaPods();
Future<bool> get hasCocoaPods => exitsHappyAsync(<String>['pod', '--version']);
String get cocoaPodsMinimumVersion => '1.0.0';
Future<String> get cocoaPodsVersionText async => (await runAsync(<String>['pod', '--version'])).processResult.stdout.trim();
Future<bool> get isCocoaPodsInstalledAndMeetsVersionCheck async {
if (!await hasCocoaPods)
return false;
try {
final Version installedVersion = new Version.parse(await cocoaPodsVersionText);
return installedVersion >= new Version.parse(cocoaPodsMinimumVersion);
} on FormatException {
return false;
}
}
/// Whether CocoaPods ran 'pod setup' once where the costly pods' specs are cloned.
Future<bool> get isCocoaPodsInitialized => fs.isDirectory(fs.path.join(homeDirPath, '.cocoapods', 'repos', 'master'));
Future<Null> processPods({
@required Directory appIosDir,
@required String iosEngineDir,
bool isSwift: false,
}) async {
if (await _checkPodCondition()) {
if (!fs.file(fs.path.join(appIosDir.path, 'Podfile')).existsSync()) {
await _createPodfile(appIosDir, isSwift);
} // TODO(xster): Add more logic for handling merge conflicts.
await _runPodInstall(appIosDir, iosEngineDir);
} else {
throwToolExit('CocoaPods not available for project using Flutter plugins');
}
}
Future<bool> _checkPodCondition() async {
if (!await isCocoaPodsInstalledAndMeetsVersionCheck) {
final String minimumVersion = cocoaPodsMinimumVersion;
printError(
'Warning: CocoaPods version $minimumVersion or greater not installed. Skipping pod install.\n'
'$noCocoaPodsConsequence\n'
'To install:\n'
'$cocoaPodsInstallInstructions\n',
emphasis: true,
);
return false;
}
if (!await isCocoaPodsInitialized) {
printError(
'Warning: CocoaPods installed but not initialized. Skipping pod install.\n'
'$noCocoaPodsConsequence\n'
'To initialize CocoaPods, run:\n'
' pod setup\n'
'once to finalize CocoaPods\' installation.',
emphasis: true,
);
return false;
}
return true;
}
Future<Null> _createPodfile(Directory bundle, bool isSwift) async {
final File podfileTemplate = fs.file(fs.path.join(
Cache.flutterRoot,
'packages',
'flutter_tools',
'templates',
'cocoapods',
isSwift ? 'Podfile-swift' : 'Podfile-objc',
));
podfileTemplate.copySync(fs.path.join(bundle.path, 'Podfile'));
}
Future<Null> _runPodInstall(Directory bundle, String engineDirectory) async {
final Status status = logger.startProgress('Running pod install...', expectSlowOperation: true);
final ProcessResult result = await processManager.run(
<String>['pod', 'install', '--verbose'],
workingDirectory: bundle.path,
environment: <String, String>{'FLUTTER_FRAMEWORK_DIR': engineDirectory},
);
status.stop();
if (logger.isVerbose || result.exitCode != 0) {
if (result.stdout.isNotEmpty) {
printStatus('CocoaPods\' output:\n↳');
printStatus(result.stdout, indent: 4);
}
if (result.stderr.isNotEmpty) {
printStatus('Error output from CocoaPods:\n↳');
printStatus(result.stderr, indent: 4);
}
}
if (result.exitCode != 0)
throwToolExit('Error running pod install');
}
}
......@@ -4,14 +4,13 @@
import 'dart:async';
import '../base/common.dart';
import '../base/context.dart';
import '../base/file_system.dart';
import '../base/os.dart';
import '../base/platform.dart';
import '../base/process.dart';
import '../base/version.dart';
import '../doctor.dart';
import 'cocoapods.dart';
import 'mac.dart';
IOSWorkflow get iosWorkflow => context.putIfAbsent(IOSWorkflow, () => new IOSWorkflow());
......@@ -43,12 +42,6 @@ class IOSWorkflow extends DoctorValidator implements Workflow {
bool get hasPythonSixModule => kPythonSix.isInstalled;
Future<bool> get hasCocoaPods => exitsHappyAsync(<String>['pod', '--version']);
String get cocoaPodsMinimumVersion => '1.0.0';
Future<String> get cocoaPodsVersionText async => (await runAsync(<String>['pod', '--version'])).processResult.stdout.trim();
Future<String> get macDevMode async => (await runAsync(<String>['DevToolsSecurity', '-status'])).processResult.stdout;
Future<bool> get _iosDeployIsInstalledAndMeetsVersionCheck async {
......@@ -62,20 +55,6 @@ class IOSWorkflow extends DoctorValidator implements Workflow {
}
}
Future<bool> get isCocoaPodsInstalledAndMeetsVersionCheck async {
if (!await hasCocoaPods)
return false;
try {
final Version installedVersion = new Version.parse(await cocoaPodsVersionText);
return installedVersion >= new Version.parse(cocoaPodsMinimumVersion);
} on FormatException {
return false;
}
}
/// Whether CocoaPods ran 'pod setup' once where the costly pods' specs are cloned.
Future<bool> get isCocoaPodsInitialized => fs.isDirectory(fs.path.join(homeDirPath, '.cocoapods', 'repos', 'master'));
@override
Future<ValidationResult> validate() async {
final List<ValidationMessage> messages = <ValidationMessage>[];
......@@ -187,9 +166,9 @@ class IOSWorkflow extends DoctorValidator implements Workflow {
}
}
if (await isCocoaPodsInstalledAndMeetsVersionCheck) {
if (await isCocoaPodsInitialized) {
messages.add(new ValidationMessage('CocoaPods version ${await cocoaPodsVersionText}'));
if (await cocoaPods.isCocoaPodsInstalledAndMeetsVersionCheck) {
if (await cocoaPods.isCocoaPodsInitialized) {
messages.add(new ValidationMessage('CocoaPods version ${await cocoaPods.cocoaPodsVersionText}'));
} else {
brewStatus = ValidationType.partial;
messages.add(new ValidationMessage.error(
......@@ -202,7 +181,7 @@ class IOSWorkflow extends DoctorValidator implements Workflow {
}
} else {
brewStatus = ValidationType.partial;
if (!await hasCocoaPods) {
if (!await cocoaPods.hasCocoaPods) {
messages.add(new ValidationMessage.error(
'CocoaPods not installed.\n'
'$noCocoaPodsConsequence\n'
......@@ -211,7 +190,7 @@ class IOSWorkflow extends DoctorValidator implements Workflow {
));
} else {
messages.add(new ValidationMessage.error(
'CocoaPods out of date ($cocoaPodsMinimumVersion is required).\n'
'CocoaPods out of date ($cocoaPods.cocoaPodsMinimumVersion is required).\n'
'$noCocoaPodsConsequence\n'
'To upgrade:\n'
'$cocoaPodsUpgradeInstructions'
......
......@@ -21,8 +21,8 @@ import '../flx.dart' as flx;
import '../globals.dart';
import '../plugins.dart';
import '../services.dart';
import 'cocoapods.dart';
import 'code_signing.dart';
import 'ios_workflow.dart';
import 'xcodeproj.dart';
const int kXcodeRequiredVersionMajor = 8;
......@@ -215,7 +215,11 @@ Future<XcodeBuildResult> buildXcodeProject({
final bool hasFlutterPlugins = injectPlugins();
if (hasFlutterPlugins)
await _runPodInstall(appDirectory, flutterFrameworkDir(mode));
await cocoaPods.processPods(
appIosDir: appDirectory,
iosEngineDir: flutterFrameworkDir(mode),
isSwift: app.isSwift,
);
updateXcodeGeneratedProperties(
projectPath: fs.currentDirectory.path,
......@@ -396,67 +400,6 @@ bool _checkXcodeVersion() {
return true;
}
final String noCocoaPodsConsequence = '''
CocoaPods is used to retrieve the iOS platform side's plugin code that responds to your plugin usage on the Dart side.
Without resolving iOS dependencies with CocoaPods, plugins will not work on iOS.
For more info, see https://flutter.io/platform-plugins''';
final String cocoaPodsInstallInstructions = '''
brew update
brew install cocoapods
pod setup''';
final String cocoaPodsUpgradeInstructions = '''
brew update
brew upgrade cocoapods
pod setup''';
Future<Null> _runPodInstall(Directory bundle, String engineDirectory) async {
if (fs.file(fs.path.join(bundle.path, 'Podfile')).existsSync()) {
if (!await iosWorkflow.isCocoaPodsInstalledAndMeetsVersionCheck) {
final String minimumVersion = iosWorkflow.cocoaPodsMinimumVersion;
printError(
'Warning: CocoaPods version $minimumVersion or greater not installed. Skipping pod install.\n'
'$noCocoaPodsConsequence\n'
'To install:\n'
'$cocoaPodsInstallInstructions\n',
emphasis: true,
);
return;
}
if (!await iosWorkflow.isCocoaPodsInitialized) {
printError(
'Warning: CocoaPods installed but not initialized. Skipping pod install.\n'
'$noCocoaPodsConsequence\n'
'To initialize CocoaPods, run:\n'
' pod setup\n'
'once to finalize CocoaPods\' installation.',
emphasis: true,
);
return;
}
final Status status = logger.startProgress('Running pod install...', expectSlowOperation: true);
final ProcessResult result = await processManager.run(
<String>['pod', 'install', '--verbose'],
workingDirectory: bundle.path,
environment: <String, String>{'FLUTTER_FRAMEWORK_DIR': engineDirectory},
);
status.stop();
if (logger.isVerbose || result.exitCode != 0) {
if (result.stdout.isNotEmpty) {
printStatus('CocoaPods\' output:\n↳');
printStatus(result.stdout, indent: 4);
}
if (result.stderr.isNotEmpty) {
printStatus('Error output from CocoaPods:\n↳');
printStatus(result.stderr, indent: 4);
}
}
if (result.exitCode != 0)
throwToolExit('Error running pod install');
}
}
Future<Null> _addServicesToBundle(Directory bundle) async {
final List<Map<String, String>> services = <Map<String, String>>[];
printTrace("Trying to resolve native pub services.");
......
......@@ -16,6 +16,17 @@ void main() {
expect(data.launchableActivityName, 'io.flutter.app.FlutterActivity');
});
});
group('BuildableIOSApp', () {
testUsingContext('check isSwift', () {
final BuildableIOSApp buildableIOSApp = new BuildableIOSApp(
projectBundleId: 'blah',
appDirectory: 'not/important',
buildSettings: _swiftBuildSettings,
);
expect(buildableIOSApp.isSwift, true);
});
});
}
final String _aaptData = '''
......@@ -44,3 +55,16 @@ locales: '--_--'
densities: '160' '240' '320' '480' '640'
native-code: 'armeabi-v7a'
''';
final Map<String, String> _swiftBuildSettings = <String, String>{
'ARCHS': 'arm64',
'ASSETCATALOG_COMPILER_APPICON_NAME': 'AppIcon',
'CLANG_ENABLE_MODULES': 'YES',
'ENABLE_BITCODE': 'NO',
'INFOPLIST_FILE': 'Runner/Info.plist',
'PRODUCT_BUNDLE_IDENTIFIER': 'com.yourcompany.test',
'PRODUCT_NAME': 'blah',
'SWIFT_OBJC_BRIDGING_HEADER': 'Runner/Runner-Bridging-Header.h',
'SWIFT_OPTIMIZATION_LEVEL': '-Onone',
'SWIFT_VERSION': '3.0',
};
// Copyright 2017 The Chromium 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 'dart:async';
import 'package:file/file.dart';
import 'package:file/memory.dart';
import 'package:flutter_tools/src/base/io.dart';
import 'package:flutter_tools/src/ios/cocoapods.dart';
import 'package:flutter_tools/src/cache.dart';
import 'package:mockito/mockito.dart';
import 'package:process/process.dart';
import 'package:test/test.dart';
import '../src/context.dart';
void main() {
FileSystem fs;
ProcessManager mockProcessManager;
Directory projectUnderTest;
CocoaPods cocoaPodsUnderTest;
setUp(() {
Cache.flutterRoot = 'flutter';
fs = new MemoryFileSystem();
mockProcessManager = new MockProcessManager();
projectUnderTest = fs.directory(fs.path.join('project', 'ios'))..createSync(recursive: true);
fs.file(fs.path.join(
Cache.flutterRoot, 'packages', 'flutter_tools', 'templates', 'cocoapods', 'Podfile-objc'
))
..createSync(recursive: true)
..writeAsStringSync('Objective-C podfile template');
fs.file(fs.path.join(
Cache.flutterRoot, 'packages', 'flutter_tools', 'templates', 'cocoapods', 'Podfile-swift'
))
..createSync(recursive: true)
..writeAsStringSync('Swift podfile template');
cocoaPodsUnderTest = const TestCocoaPods();
when(mockProcessManager.run(
<String>['pod', 'install', '--verbose'],
workingDirectory: 'project/ios',
environment: <String, String>{'FLUTTER_FRAMEWORK_DIR': 'engine/path'},
)).thenReturn(exitsHappy);
});
testUsingContext(
'create objective-c Podfile when not present',
() async {
await cocoaPodsUnderTest.processPods(
appIosDir: projectUnderTest,
iosEngineDir: 'engine/path',
);
expect(fs.file(fs.path.join('project', 'ios', 'Podfile')).readAsStringSync() , 'Objective-C podfile template');
verify(mockProcessManager.run(
<String>['pod', 'install', '--verbose'],
workingDirectory: 'project/ios',
environment: <String, String>{'FLUTTER_FRAMEWORK_DIR': 'engine/path'},
));
},
overrides: <Type, Generator>{
FileSystem: () => fs,
ProcessManager: () => mockProcessManager,
},
);
testUsingContext(
'create swift Podfile if swift',
() async {
await cocoaPodsUnderTest.processPods(
appIosDir: projectUnderTest,
iosEngineDir: 'engine/path',
isSwift: true,
);
expect(fs.file(fs.path.join('project', 'ios', 'Podfile')).readAsStringSync() , 'Swift podfile template');
verify(mockProcessManager.run(
<String>['pod', 'install', '--verbose'],
workingDirectory: 'project/ios',
environment: <String, String>{'FLUTTER_FRAMEWORK_DIR': 'engine/path'},
));
},
overrides: <Type, Generator>{
FileSystem: () => fs,
ProcessManager: () => mockProcessManager,
},
);
testUsingContext(
'do not recreate Podfile when present',
() async {
fs.file(fs.path.join('project', 'ios', 'Podfile'))
..createSync()
..writeAsString('Existing Podfile');
await cocoaPodsUnderTest.processPods(
appIosDir: projectUnderTest,
iosEngineDir: 'engine/path',
); expect(fs.file(fs.path.join('project', 'ios', 'Podfile')).readAsStringSync() , 'Existing Podfile');
verify(mockProcessManager.run(
<String>['pod', 'install', '--verbose'],
workingDirectory: 'project/ios',
environment: <String, String>{'FLUTTER_FRAMEWORK_DIR': 'engine/path'},
));
},
overrides: <Type, Generator>{
FileSystem: () => fs,
ProcessManager: () => mockProcessManager,
},
);
testUsingContext(
'missing CocoaPods throws',
() async {
cocoaPodsUnderTest = const TestCocoaPods(false);
try {
await cocoaPodsUnderTest.processPods(
appIosDir: projectUnderTest,
iosEngineDir: 'engine/path',
);
fail('Expected tool error');
} catch (ToolExit) {
verifyNever(mockProcessManager.run(
<String>['pod', 'install', '--verbose'],
workingDirectory: 'project/ios',
environment: <String, String>{'FLUTTER_FRAMEWORK_DIR': 'engine/path'},
));
}
},
overrides: <Type, Generator>{
FileSystem: () => fs,
ProcessManager: () => mockProcessManager,
},
);
}
class MockProcessManager extends Mock implements ProcessManager {}
class TestCocoaPods extends CocoaPods {
const TestCocoaPods([this._hasCocoaPods = true]);
final bool _hasCocoaPods;
@override
Future<bool> get hasCocoaPods => new Future<bool>.value(_hasCocoaPods);
@override
Future<String> get cocoaPodsVersionText async => new Future<String>.value('1.5.0');
@override
Future<bool> get isCocoaPodsInitialized => new Future<bool>.value(true);
}
final ProcessResult exitsHappy = new ProcessResult(
1, // pid
0, // exitCode
'', // stdout
'', // stderr
);
\ No newline at end of file
......@@ -9,6 +9,7 @@ import 'package:flutter_tools/src/base/common.dart';
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/io.dart';
import 'package:flutter_tools/src/doctor.dart';
import 'package:flutter_tools/src/ios/cocoapods.dart';
import 'package:flutter_tools/src/ios/ios_workflow.dart';
import 'package:flutter_tools/src/ios/mac.dart';
import 'package:mockito/mockito.dart';
......@@ -22,13 +23,18 @@ void main() {
MockIMobileDevice iMobileDevice;
MockXcode xcode;
MockProcessManager processManager;
MockCocoaPods cocoaPods;
FileSystem fs;
setUp(() {
iMobileDevice = new MockIMobileDevice();
xcode = new MockXcode();
processManager = new MockProcessManager();
cocoaPods = new MockCocoaPods();
fs = new MemoryFileSystem();
when(cocoaPods.isCocoaPodsInstalledAndMeetsVersionCheck).thenReturn(true);
when(cocoaPods.isCocoaPodsInitialized).thenReturn(true);
});
testUsingContext('Emit missing status when nothing is installed', () async {
......@@ -44,6 +50,7 @@ void main() {
}, overrides: <Type, Generator>{
IMobileDevice: () => iMobileDevice,
Xcode: () => xcode,
CocoaPods: () => cocoaPods,
});
testUsingContext('Emits partial status when Xcode is not installed', () async {
......@@ -55,6 +62,7 @@ void main() {
}, overrides: <Type, Generator>{
IMobileDevice: () => iMobileDevice,
Xcode: () => xcode,
CocoaPods: () => cocoaPods,
});
testUsingContext('Emits partial status when Xcode is partially installed', () async {
......@@ -66,6 +74,7 @@ void main() {
}, overrides: <Type, Generator>{
IMobileDevice: () => iMobileDevice,
Xcode: () => xcode,
CocoaPods: () => cocoaPods,
});
testUsingContext('Emits partial status when Xcode version too low', () async {
......@@ -80,6 +89,7 @@ void main() {
}, overrides: <Type, Generator>{
IMobileDevice: () => iMobileDevice,
Xcode: () => xcode,
CocoaPods: () => cocoaPods,
});
testUsingContext('Emits partial status when Xcode EULA not signed', () async {
......@@ -94,6 +104,7 @@ void main() {
}, overrides: <Type, Generator>{
IMobileDevice: () => iMobileDevice,
Xcode: () => xcode,
CocoaPods: () => cocoaPods,
});
testUsingContext('Emits partial status when Mac dev mode was never enabled', () async {
......@@ -108,6 +119,7 @@ void main() {
}, overrides: <Type, Generator>{
IMobileDevice: () => iMobileDevice,
Xcode: () => xcode,
CocoaPods: () => cocoaPods,
});
testUsingContext('Emits partial status when python six not installed', () async {
......@@ -122,6 +134,7 @@ void main() {
}, overrides: <Type, Generator>{
IMobileDevice: () => iMobileDevice,
Xcode: () => xcode,
CocoaPods: () => cocoaPods,
});
testUsingContext('Emits partial status when homebrew not installed', () async {
......@@ -136,6 +149,7 @@ void main() {
}, overrides: <Type, Generator>{
IMobileDevice: () => iMobileDevice,
Xcode: () => xcode,
CocoaPods: () => cocoaPods,
});
testUsingContext('Emits partial status when libimobiledevice is not installed', () async {
......@@ -150,6 +164,7 @@ void main() {
}, overrides: <Type, Generator>{
IMobileDevice: () => new MockIMobileDevice(isWorking: false),
Xcode: () => xcode,
CocoaPods: () => cocoaPods,
});
testUsingContext('Emits partial status when ios-deploy is not installed', () async {
......@@ -164,6 +179,7 @@ void main() {
}, overrides: <Type, Generator>{
IMobileDevice: () => iMobileDevice,
Xcode: () => xcode,
CocoaPods: () => cocoaPods,
});
testUsingContext('Emits partial status when ios-deploy version is too low', () async {
......@@ -178,6 +194,7 @@ void main() {
}, overrides: <Type, Generator>{
IMobileDevice: () => iMobileDevice,
Xcode: () => xcode,
CocoaPods: () => cocoaPods,
});
testUsingContext('Emits partial status when CocoaPods is not installed', () async {
......@@ -186,12 +203,15 @@ void main() {
.thenReturn('Xcode 8.2.1\nBuild version 8C1002\n');
when(xcode.isInstalledAndMeetsVersionCheck).thenReturn(true);
when(xcode.eulaSigned).thenReturn(true);
final IOSWorkflowTestTarget workflow = new IOSWorkflowTestTarget(hasCocoaPods: false);
when(cocoaPods.isCocoaPodsInstalledAndMeetsVersionCheck).thenReturn(false);
when(cocoaPods.hasCocoaPods).thenReturn(false);
final IOSWorkflowTestTarget workflow = new IOSWorkflowTestTarget();
final ValidationResult result = await workflow.validate();
expect(result.type, ValidationType.partial);
}, overrides: <Type, Generator>{
IMobileDevice: () => iMobileDevice,
Xcode: () => xcode,
CocoaPods: () => cocoaPods,
});
testUsingContext('Emits partial status when CocoaPods version is too low', () async {
......@@ -200,12 +220,16 @@ void main() {
.thenReturn('Xcode 8.2.1\nBuild version 8C1002\n');
when(xcode.isInstalledAndMeetsVersionCheck).thenReturn(true);
when(xcode.eulaSigned).thenReturn(true);
final IOSWorkflowTestTarget workflow = new IOSWorkflowTestTarget(cocoaPodsVersionText: '0.39.0');
when(cocoaPods.isCocoaPodsInstalledAndMeetsVersionCheck).thenReturn(false);
when(cocoaPods.hasCocoaPods).thenReturn(true);
when(cocoaPods.cocoaPodsVersionText).thenReturn('0.39.0');
final IOSWorkflowTestTarget workflow = new IOSWorkflowTestTarget();
final ValidationResult result = await workflow.validate();
expect(result.type, ValidationType.partial);
}, overrides: <Type, Generator>{
IMobileDevice: () => iMobileDevice,
Xcode: () => xcode,
CocoaPods: () => cocoaPods,
});
testUsingContext('Emits partial status when CocoaPods is not initialized', () async {
......@@ -214,6 +238,9 @@ void main() {
.thenReturn('Xcode 8.2.1\nBuild version 8C1002\n');
when(xcode.isInstalledAndMeetsVersionCheck).thenReturn(true);
when(xcode.eulaSigned).thenReturn(true);
when(cocoaPods.isCocoaPodsInstalledAndMeetsVersionCheck).thenReturn(false);
when(cocoaPods.hasCocoaPods).thenReturn(true);
when(cocoaPods.isCocoaPodsInitialized).thenReturn(false);
final ValidationResult result = await new IOSWorkflowTestTarget().validate();
expect(result.type, ValidationType.partial);
......@@ -221,6 +248,7 @@ void main() {
FileSystem: () => fs,
IMobileDevice: () => iMobileDevice,
Xcode: () => xcode,
CocoaPods: () => cocoaPods,
ProcessManager: () => processManager,
});
......@@ -239,6 +267,7 @@ void main() {
FileSystem: () => fs,
IMobileDevice: () => iMobileDevice,
Xcode: () => xcode,
CocoaPods: () => cocoaPods,
ProcessManager: () => processManager,
});
});
......@@ -260,6 +289,7 @@ class MockIMobileDevice extends IMobileDevice {
class MockXcode extends Mock implements Xcode {}
class MockProcessManager extends Mock implements ProcessManager {}
class MockCocoaPods extends Mock implements CocoaPods {}
class IOSWorkflowTestTarget extends IOSWorkflow {
IOSWorkflowTestTarget({
......@@ -268,14 +298,10 @@ class IOSWorkflowTestTarget extends IOSWorkflow {
bool hasIosDeploy: true,
String iosDeployVersionText: '1.9.0',
bool hasIDeviceInstaller: true,
bool hasCocoaPods: true,
String cocoaPodsVersionText: '1.2.0',
String macDevMode: 'Developer mode is already enabled.',
}) : hasIosDeploy = new Future<bool>.value(hasIosDeploy),
iosDeployVersionText = new Future<String>.value(iosDeployVersionText),
hasIDeviceInstaller = new Future<bool>.value(hasIDeviceInstaller),
hasCocoaPods = new Future<bool>.value(hasCocoaPods),
cocoaPodsVersionText = new Future<String>.value(cocoaPodsVersionText),
macDevMode = new Future<String>.value(macDevMode);
@override
......@@ -293,12 +319,6 @@ class IOSWorkflowTestTarget extends IOSWorkflow {
@override
final Future<bool> hasIDeviceInstaller;
@override
final Future<bool> hasCocoaPods;
@override
final Future<String> cocoaPodsVersionText;
@override
final Future<String> macDevMode;
}
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