blob: bc2afa6f436b383dce2e002cf584d9b65ee0865f [file] [log] [blame]
xster6a494192017-07-12 18:35:08 -07001// Copyright 2017 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5import 'dart:async';
6
7import 'package:file/file.dart';
8import 'package:file/memory.dart';
Mikkel Nygaard Ravn20004352018-02-16 10:17:28 +01009import 'package:flutter_tools/src/base/common.dart';
xster6a494192017-07-12 18:35:08 -070010import 'package:flutter_tools/src/base/io.dart';
Dan Field704814c2019-02-05 16:03:37 -080011import 'package:flutter_tools/src/base/platform.dart';
Mikkel Nygaard Ravnc2e1bc02018-02-15 22:55:36 +010012import 'package:flutter_tools/src/cache.dart';
stuartmorgan81c38b22019-05-24 22:51:02 -040013import 'package:flutter_tools/src/ios/xcodeproj.dart';
14import 'package:flutter_tools/src/macos/cocoapods.dart';
KyleWong60aa49e2019-01-30 12:33:16 +080015import 'package:flutter_tools/src/plugins.dart';
Sigurd Meldgaard1e8ef602018-06-28 14:35:00 +020016import 'package:flutter_tools/src/project.dart';
xster6a494192017-07-12 18:35:08 -070017import 'package:mockito/mockito.dart';
18import 'package:process/process.dart';
xster6a494192017-07-12 18:35:08 -070019
Ian Hickson686d8f82018-08-14 20:33:58 -070020import '../src/common.dart';
xster6a494192017-07-12 18:35:08 -070021import '../src/context.dart';
22
Alexandre Ardhuina07d3712018-09-14 21:06:19 +020023typedef InvokeProcess = Future<ProcessResult> Function();
Mikkel Nygaard Ravn61c71712018-05-08 08:02:39 +020024
xster6a494192017-07-12 18:35:08 -070025void main() {
26 FileSystem fs;
27 ProcessManager mockProcessManager;
Mikkel Nygaard Ravn20004352018-02-16 10:17:28 +010028 MockXcodeProjectInterpreter mockXcodeProjectInterpreter;
Sigurd Meldgaard2d3a5c72018-07-20 08:00:30 +020029 FlutterProject projectUnderTest;
xster6a494192017-07-12 18:35:08 -070030 CocoaPods cocoaPodsUnderTest;
Mikkel Nygaard Ravn61c71712018-05-08 08:02:39 +020031 InvokeProcess resultOfPodVersion;
32
33 void pretendPodIsNotInstalled() {
34 resultOfPodVersion = () async => throw 'Executable does not exist';
35 }
36
37 void pretendPodVersionFails() {
38 resultOfPodVersion = () async => exitsWithError();
39 }
40
41 void pretendPodVersionIs(String versionText) {
42 resultOfPodVersion = () async => exitsHappy(versionText);
43 }
xster6a494192017-07-12 18:35:08 -070044
Dan Field704814c2019-02-05 16:03:37 -080045 void podsIsInHomeDir() {
46 fs.directory(fs.path.join(homeDirPath, '.cocoapods', 'repos', 'master')).createSync(recursive: true);
47 }
48
49 String podsIsInCustomDir({String cocoapodsReposDir}) {
50 cocoapodsReposDir ??= fs.path.join(homeDirPath, 'cache', 'cocoapods', 'repos');
51 fs.directory(fs.path.join(cocoapodsReposDir, 'master')).createSync(recursive: true);
52 return cocoapodsReposDir;
53 }
54
Mikkel Nygaard Ravnb2800742018-08-02 14:12:25 +020055 setUp(() async {
xster6a494192017-07-12 18:35:08 -070056 Cache.flutterRoot = 'flutter';
Alexandre Ardhuind927c932018-09-12 08:29:29 +020057 fs = MemoryFileSystem();
58 mockProcessManager = MockProcessManager();
59 mockXcodeProjectInterpreter = MockXcodeProjectInterpreter();
Jonah Williams4ff46712019-04-29 08:21:32 -070060 projectUnderTest = FlutterProject.fromDirectory(fs.directory('project'));
Mikkel Nygaard Ravna600fe72018-09-25 21:21:13 +020061 projectUnderTest.ios.xcodeProject.createSync(recursive: true);
Alexandre Ardhuind927c932018-09-12 08:29:29 +020062 cocoaPodsUnderTest = CocoaPods();
Jenn Magderc8bf7ab2019-06-10 14:30:28 -070063 pretendPodVersionIs('1.6.0');
xster6a494192017-07-12 18:35:08 -070064 fs.file(fs.path.join(
stuartmorgan3ebebeb2019-05-31 13:19:44 -070065 Cache.flutterRoot, 'packages', 'flutter_tools', 'templates', 'cocoapods', 'Podfile-ios-objc',
xster6a494192017-07-12 18:35:08 -070066 ))
67 ..createSync(recursive: true)
stuartmorgan3ebebeb2019-05-31 13:19:44 -070068 ..writeAsStringSync('Objective-C iOS podfile template');
xster6a494192017-07-12 18:35:08 -070069 fs.file(fs.path.join(
stuartmorgan3ebebeb2019-05-31 13:19:44 -070070 Cache.flutterRoot, 'packages', 'flutter_tools', 'templates', 'cocoapods', 'Podfile-ios-swift',
xster6a494192017-07-12 18:35:08 -070071 ))
72 ..createSync(recursive: true)
stuartmorgan3ebebeb2019-05-31 13:19:44 -070073 ..writeAsStringSync('Swift iOS podfile template');
74 fs.file(fs.path.join(
75 Cache.flutterRoot, 'packages', 'flutter_tools', 'templates', 'cocoapods', 'Podfile-macos',
76 ))
77 ..createSync(recursive: true)
78 ..writeAsStringSync('macOS podfile template');
Mikkel Nygaard Ravn61c71712018-05-08 08:02:39 +020079 when(mockProcessManager.run(
80 <String>['pod', '--version'],
Sam Rawlinsfba81d02018-05-31 08:24:26 -070081 workingDirectory: anyNamed('workingDirectory'),
82 environment: anyNamed('environment'),
Mikkel Nygaard Ravn61c71712018-05-08 08:02:39 +020083 )).thenAnswer((_) => resultOfPodVersion());
xster6a494192017-07-12 18:35:08 -070084 when(mockProcessManager.run(
85 <String>['pod', 'install', '--verbose'],
86 workingDirectory: 'project/ios',
xster07590432017-12-27 02:51:44 -080087 environment: <String, String>{'FLUTTER_FRAMEWORK_DIR': 'engine/path', 'COCOAPODS_DISABLE_STATS': 'true'},
Mikkel Nygaard Ravn61c71712018-05-08 08:02:39 +020088 )).thenAnswer((_) async => exitsHappy());
stuartmorgan3ebebeb2019-05-31 13:19:44 -070089 when(mockProcessManager.run(
90 <String>['pod', 'install', '--verbose'],
91 workingDirectory: 'project/macos',
92 environment: <String, String>{'FLUTTER_FRAMEWORK_DIR': 'engine/path', 'COCOAPODS_DISABLE_STATS': 'true'},
93 )).thenAnswer((_) async => exitsHappy());
Mikkel Nygaard Ravn61c71712018-05-08 08:02:39 +020094 });
95
96 group('Evaluate installation', () {
97 testUsingContext('detects not installed, if pod exec does not exist', () async {
98 pretendPodIsNotInstalled();
99 expect(await cocoaPodsUnderTest.evaluateCocoaPodsInstallation, CocoaPodsStatus.notInstalled);
100 }, overrides: <Type, Generator>{
101 ProcessManager: () => mockProcessManager,
102 });
103
104 testUsingContext('detects not installed, if pod version fails', () async {
105 pretendPodVersionFails();
106 expect(await cocoaPodsUnderTest.evaluateCocoaPodsInstallation, CocoaPodsStatus.notInstalled);
107 }, overrides: <Type, Generator>{
108 ProcessManager: () => mockProcessManager,
109 });
110
111 testUsingContext('detects installed', () async {
112 pretendPodVersionIs('0.0.1');
113 expect(await cocoaPodsUnderTest.evaluateCocoaPodsInstallation, isNot(CocoaPodsStatus.notInstalled));
114 }, overrides: <Type, Generator>{
115 ProcessManager: () => mockProcessManager,
116 });
117
KyleWong85ded442019-01-03 11:57:03 +0800118 testUsingContext('detects unknown version', () async {
119 pretendPodVersionIs('Plugin loaded.\n1.5.3');
120 expect(await cocoaPodsUnderTest.evaluateCocoaPodsInstallation, CocoaPodsStatus.unknownVersion);
121 }, overrides: <Type, Generator>{
122 ProcessManager: () => mockProcessManager,
123 });
124
Mikkel Nygaard Ravn61c71712018-05-08 08:02:39 +0200125 testUsingContext('detects below minimum version', () async {
Jenn Magderc8bf7ab2019-06-10 14:30:28 -0700126 pretendPodVersionIs('1.5.0');
Mikkel Nygaard Ravn61c71712018-05-08 08:02:39 +0200127 expect(await cocoaPodsUnderTest.evaluateCocoaPodsInstallation, CocoaPodsStatus.belowMinimumVersion);
128 }, overrides: <Type, Generator>{
129 ProcessManager: () => mockProcessManager,
130 });
131
Mikkel Nygaard Ravn61c71712018-05-08 08:02:39 +0200132 testUsingContext('detects at recommended version', () async {
Jenn Magderc8bf7ab2019-06-10 14:30:28 -0700133 pretendPodVersionIs('1.6.0');
Mikkel Nygaard Ravn61c71712018-05-08 08:02:39 +0200134 expect(await cocoaPodsUnderTest.evaluateCocoaPodsInstallation, CocoaPodsStatus.recommended);
135 }, overrides: <Type, Generator>{
136 ProcessManager: () => mockProcessManager,
137 });
138
139 testUsingContext('detects above recommended version', () async {
Jenn Magderc8bf7ab2019-06-10 14:30:28 -0700140 pretendPodVersionIs('1.6.1');
Mikkel Nygaard Ravn61c71712018-05-08 08:02:39 +0200141 expect(await cocoaPodsUnderTest.evaluateCocoaPodsInstallation, CocoaPodsStatus.recommended);
142 }, overrides: <Type, Generator>{
143 ProcessManager: () => mockProcessManager,
144 });
xster6a494192017-07-12 18:35:08 -0700145 });
146
Mikkel Nygaard Ravn20004352018-02-16 10:17:28 +0100147 group('Setup Podfile', () {
Sigurd Meldgaard6a8f9042018-07-16 16:21:20 +0200148 testUsingContext('creates objective-c Podfile when not present', () async {
Sigurd Meldgaard2d3a5c72018-07-20 08:00:30 +0200149 cocoaPodsUnderTest.setupPodfile(projectUnderTest.ios);
Sigurd Meldgaard6a8f9042018-07-16 16:21:20 +0200150
stuartmorgan3ebebeb2019-05-31 13:19:44 -0700151 expect(projectUnderTest.ios.podfile.readAsStringSync(), 'Objective-C iOS podfile template');
Mikkel Nygaard Ravn20004352018-02-16 10:17:28 +0100152 }, overrides: <Type, Generator>{
153 FileSystem: () => fs,
154 });
155
Sigurd Meldgaard1e8ef602018-06-28 14:35:00 +0200156 testUsingContext('creates swift Podfile if swift', () async {
Mikkel Nygaard Ravn0d596792018-03-07 08:41:23 +0100157 when(mockXcodeProjectInterpreter.isInstalled).thenReturn(true);
Sam Rawlins9f8a70b2018-06-21 16:23:47 -0700158 when(mockXcodeProjectInterpreter.getBuildSettings(any, any)).thenReturn(<String, String>{
Mikkel Nygaard Ravn20004352018-02-16 10:17:28 +0100159 'SWIFT_VERSION': '4.0',
160 });
161
Jonah Williams4ff46712019-04-29 08:21:32 -0700162 final FlutterProject project = FlutterProject.fromPath('project');
Sigurd Meldgaard2d3a5c72018-07-20 08:00:30 +0200163 cocoaPodsUnderTest.setupPodfile(project.ios);
Mikkel Nygaard Ravn20004352018-02-16 10:17:28 +0100164
stuartmorgan3ebebeb2019-05-31 13:19:44 -0700165 expect(projectUnderTest.ios.podfile.readAsStringSync(), 'Swift iOS podfile template');
Mikkel Nygaard Ravn20004352018-02-16 10:17:28 +0100166 }, overrides: <Type, Generator>{
167 FileSystem: () => fs,
168 XcodeProjectInterpreter: () => mockXcodeProjectInterpreter,
169 });
170
stuartmorgan3ebebeb2019-05-31 13:19:44 -0700171 testUsingContext('creates macOS Podfile when not present', () async {
172 projectUnderTest.macos.xcodeProject.createSync(recursive: true);
173 cocoaPodsUnderTest.setupPodfile(projectUnderTest.macos);
174
175 expect(projectUnderTest.macos.podfile.readAsStringSync(), 'macOS podfile template');
176 }, overrides: <Type, Generator>{
177 FileSystem: () => fs,
178 });
179
Sigurd Meldgaard1e8ef602018-06-28 14:35:00 +0200180 testUsingContext('does not recreate Podfile when already present', () async {
Sigurd Meldgaard2d3a5c72018-07-20 08:00:30 +0200181 projectUnderTest.ios.podfile..createSync()..writeAsStringSync('Existing Podfile');
Mikkel Nygaard Ravn20004352018-02-16 10:17:28 +0100182
Jonah Williams4ff46712019-04-29 08:21:32 -0700183 final FlutterProject project = FlutterProject.fromPath('project');
Sigurd Meldgaard2d3a5c72018-07-20 08:00:30 +0200184 cocoaPodsUnderTest.setupPodfile(project.ios);
Mikkel Nygaard Ravn20004352018-02-16 10:17:28 +0100185
Sigurd Meldgaard2d3a5c72018-07-20 08:00:30 +0200186 expect(projectUnderTest.ios.podfile.readAsStringSync(), 'Existing Podfile');
Mikkel Nygaard Ravn20004352018-02-16 10:17:28 +0100187 }, overrides: <Type, Generator>{
188 FileSystem: () => fs,
189 });
190
Sigurd Meldgaard1e8ef602018-06-28 14:35:00 +0200191 testUsingContext('does not create Podfile when we cannot interpret Xcode projects', () async {
Mikkel Nygaard Ravn0d596792018-03-07 08:41:23 +0100192 when(mockXcodeProjectInterpreter.isInstalled).thenReturn(false);
Mikkel Nygaard Ravn20004352018-02-16 10:17:28 +0100193
Jonah Williams4ff46712019-04-29 08:21:32 -0700194 final FlutterProject project = FlutterProject.fromPath('project');
Sigurd Meldgaard2d3a5c72018-07-20 08:00:30 +0200195 cocoaPodsUnderTest.setupPodfile(project.ios);
Mikkel Nygaard Ravn20004352018-02-16 10:17:28 +0100196
Sigurd Meldgaard2d3a5c72018-07-20 08:00:30 +0200197 expect(projectUnderTest.ios.podfile.existsSync(), false);
Mikkel Nygaard Ravn20004352018-02-16 10:17:28 +0100198 }, overrides: <Type, Generator>{
199 FileSystem: () => fs,
200 XcodeProjectInterpreter: () => mockXcodeProjectInterpreter,
201 });
202
Sigurd Meldgaard1e8ef602018-06-28 14:35:00 +0200203 testUsingContext('includes Pod config in xcconfig files, if not present', () async {
Sigurd Meldgaard2d3a5c72018-07-20 08:00:30 +0200204 projectUnderTest.ios.podfile..createSync()..writeAsStringSync('Existing Podfile');
205 projectUnderTest.ios.xcodeConfigFor('Debug')
206 ..createSync(recursive: true)
207 ..writeAsStringSync('Existing debug config');
208 projectUnderTest.ios.xcodeConfigFor('Release')
209 ..createSync(recursive: true)
210 ..writeAsStringSync('Existing release config');
Mikkel Nygaard Ravn20004352018-02-16 10:17:28 +0100211
Jonah Williams4ff46712019-04-29 08:21:32 -0700212 final FlutterProject project = FlutterProject.fromPath('project');
Sigurd Meldgaard2d3a5c72018-07-20 08:00:30 +0200213 cocoaPodsUnderTest.setupPodfile(project.ios);
Mikkel Nygaard Ravn20004352018-02-16 10:17:28 +0100214
Sigurd Meldgaard2d3a5c72018-07-20 08:00:30 +0200215 final String debugContents = projectUnderTest.ios.xcodeConfigFor('Debug').readAsStringSync();
Mikkel Nygaard Ravn20004352018-02-16 10:17:28 +0100216 expect(debugContents, contains(
217 '#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"\n'));
218 expect(debugContents, contains('Existing debug config'));
Sigurd Meldgaard2d3a5c72018-07-20 08:00:30 +0200219 final String releaseContents = projectUnderTest.ios.xcodeConfigFor('Release').readAsStringSync();
Mikkel Nygaard Ravn20004352018-02-16 10:17:28 +0100220 expect(releaseContents, contains(
221 '#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"\n'));
222 expect(releaseContents, contains('Existing release config'));
223 }, overrides: <Type, Generator>{
224 FileSystem: () => fs,
225 });
226 });
227
KyleWong60aa49e2019-01-30 12:33:16 +0800228 group('Update xcconfig', () {
229 testUsingContext('includes Pod config in xcconfig files, if the user manually added Pod dependencies without using Flutter plugins', () async {
230 projectUnderTest.ios.podfile..createSync()..writeAsStringSync('Custom Podfile');
231 projectUnderTest.ios.podfileLock..createSync()..writeAsStringSync('Podfile.lock from user executed `pod install`');
232 projectUnderTest.packagesFile..createSync()..writeAsStringSync('');
233 projectUnderTest.ios.xcodeConfigFor('Debug')
234 ..createSync(recursive: true)
235 ..writeAsStringSync('Existing debug config');
236 projectUnderTest.ios.xcodeConfigFor('Release')
237 ..createSync(recursive: true)
238 ..writeAsStringSync('Existing release config');
239
Jonah Williams4ff46712019-04-29 08:21:32 -0700240 final FlutterProject project = FlutterProject.fromPath('project');
KyleWong60aa49e2019-01-30 12:33:16 +0800241 await injectPlugins(project);
242
243 final String debugContents = projectUnderTest.ios.xcodeConfigFor('Debug').readAsStringSync();
244 expect(debugContents, contains(
245 '#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"\n'));
246 expect(debugContents, contains('Existing debug config'));
247 final String releaseContents = projectUnderTest.ios.xcodeConfigFor('Release').readAsStringSync();
248 expect(releaseContents, contains(
249 '#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"\n'));
250 expect(releaseContents, contains('Existing release config'));
251 }, overrides: <Type, Generator>{
252 FileSystem: () => fs,
253 });
254 });
255
Mikkel Nygaard Ravn20004352018-02-16 10:17:28 +0100256 group('Process pods', () {
Dan Field704814c2019-02-05 16:03:37 -0800257 setUp(() {
258 podsIsInHomeDir();
259 });
260
Mikkel Nygaard Ravn20004352018-02-16 10:17:28 +0100261 testUsingContext('prints error, if CocoaPods is not installed', () async {
Mikkel Nygaard Ravn61c71712018-05-08 08:02:39 +0200262 pretendPodIsNotInstalled();
Sigurd Meldgaard2d3a5c72018-07-20 08:00:30 +0200263 projectUnderTest.ios.podfile.createSync();
Chris Brackencdbdafa2018-05-03 19:40:16 -0700264 final bool didInstall = await cocoaPodsUnderTest.processPods(
stuartmorgan3ebebeb2019-05-31 13:19:44 -0700265 xcodeProject: projectUnderTest.ios,
266 engineDir: 'engine/path',
Mikkel Nygaard Ravn20004352018-02-16 10:17:28 +0100267 );
268 verifyNever(mockProcessManager.run(
Sam Rawlins9f8a70b2018-06-21 16:23:47 -0700269 argThat(containsAllInOrder(<String>['pod', 'install'])),
Sam Rawlinsfba81d02018-05-31 08:24:26 -0700270 workingDirectory: anyNamed('workingDirectory'),
Sam Rawlins1f76f7f2018-05-16 10:19:05 -0700271 environment: anyNamed('environment'),
Mikkel Nygaard Ravn20004352018-02-16 10:17:28 +0100272 ));
273 expect(testLogger.errorText, contains('not installed'));
274 expect(testLogger.errorText, contains('Skipping pod install'));
Chris Brackencdbdafa2018-05-03 19:40:16 -0700275 expect(didInstall, isFalse);
Mikkel Nygaard Ravn20004352018-02-16 10:17:28 +0100276 }, overrides: <Type, Generator>{
277 FileSystem: () => fs,
278 ProcessManager: () => mockProcessManager,
279 });
280
281 testUsingContext('throws, if Podfile is missing.', () async {
xster6a494192017-07-12 18:35:08 -0700282 try {
283 await cocoaPodsUnderTest.processPods(
stuartmorgan3ebebeb2019-05-31 13:19:44 -0700284 xcodeProject: projectUnderTest.ios,
285 engineDir: 'engine/path',
xster6a494192017-07-12 18:35:08 -0700286 );
Mikkel Nygaard Ravn20004352018-02-16 10:17:28 +0100287 fail('ToolExit expected');
288 } catch(e) {
Ian Hickson686d8f82018-08-14 20:33:58 -0700289 expect(e, isInstanceOf<ToolExit>());
xster6a494192017-07-12 18:35:08 -0700290 verifyNever(mockProcessManager.run(
Sam Rawlins9f8a70b2018-06-21 16:23:47 -0700291 argThat(containsAllInOrder(<String>['pod', 'install'])),
Sam Rawlinsfba81d02018-05-31 08:24:26 -0700292 workingDirectory: anyNamed('workingDirectory'),
Sam Rawlins1f76f7f2018-05-16 10:19:05 -0700293 environment: anyNamed('environment'),
xster6a494192017-07-12 18:35:08 -0700294 ));
295 }
Mikkel Nygaard Ravn20004352018-02-16 10:17:28 +0100296 }, overrides: <Type, Generator>{
xster6a494192017-07-12 18:35:08 -0700297 FileSystem: () => fs,
298 ProcessManager: () => mockProcessManager,
Mikkel Nygaard Ravn20004352018-02-16 10:17:28 +0100299 });
xstere9403812017-11-10 12:41:58 -0800300
Mikkel Nygaard Ravn20004352018-02-16 10:17:28 +0100301 testUsingContext('throws, if specs repo is outdated.', () async {
xstere9403812017-11-10 12:41:58 -0800302 fs.file(fs.path.join('project', 'ios', 'Podfile'))
303 ..createSync()
Mikkel Nygaard Ravn61c71712018-05-08 08:02:39 +0200304 ..writeAsStringSync('Existing Podfile');
xstere9403812017-11-10 12:41:58 -0800305
306 when(mockProcessManager.run(
307 <String>['pod', 'install', '--verbose'],
308 workingDirectory: 'project/ios',
Mikkel Nygaard Ravn20004352018-02-16 10:17:28 +0100309 environment: <String, String>{
310 'FLUTTER_FRAMEWORK_DIR': 'engine/path',
311 'COCOAPODS_DISABLE_STATS': 'true',
312 },
Mikkel Nygaard Ravn61c71712018-05-08 08:02:39 +0200313 )).thenAnswer((_) async => exitsWithError(
xstere9403812017-11-10 12:41:58 -0800314 '''
315[!] Unable to satisfy the following requirements:
316
317- `Firebase/Auth` required by `Podfile`
318- `Firebase/Auth (= 4.0.0)` required by `Podfile.lock`
319
320None of your spec sources contain a spec satisfying the dependencies: `Firebase/Auth, Firebase/Auth (= 4.0.0)`.
321
322You have either:
323 * out-of-date source repos which you can update with `pod repo update` or with `pod install --repo-update`.
324 * mistyped the name or version.
325 * not added the source repo that hosts the Podspec to your Podfile.
326
327Note: as of CocoaPods 1.0, `pod repo update` does not happen on `pod install` by default.''',
Mikkel Nygaard Ravn61c71712018-05-08 08:02:39 +0200328 ));
xstere9403812017-11-10 12:41:58 -0800329 try {
330 await cocoaPodsUnderTest.processPods(
stuartmorgan3ebebeb2019-05-31 13:19:44 -0700331 xcodeProject: projectUnderTest.ios,
332 engineDir: 'engine/path',
Mikkel Nygaard Ravn20004352018-02-16 10:17:28 +0100333 );
334 fail('ToolExit expected');
335 } catch (e) {
Ian Hickson686d8f82018-08-14 20:33:58 -0700336 expect(e, isInstanceOf<ToolExit>());
Mikkel Nygaard Ravn20004352018-02-16 10:17:28 +0100337 expect(
338 testLogger.errorText,
339 contains("CocoaPods's specs repository is too out-of-date to satisfy dependencies"),
340 );
xstere9403812017-11-10 12:41:58 -0800341 }
Mikkel Nygaard Ravn20004352018-02-16 10:17:28 +0100342 }, overrides: <Type, Generator>{
xstere9403812017-11-10 12:41:58 -0800343 FileSystem: () => fs,
344 ProcessManager: () => mockProcessManager,
Mikkel Nygaard Ravn20004352018-02-16 10:17:28 +0100345 });
xster4d2c2aa2017-12-27 07:30:31 -0800346
Mikkel Nygaard Ravn20004352018-02-16 10:17:28 +0100347 testUsingContext('run pod install, if Podfile.lock is missing', () async {
Sigurd Meldgaard2d3a5c72018-07-20 08:00:30 +0200348 projectUnderTest.ios.podfile
xster4d2c2aa2017-12-27 07:30:31 -0800349 ..createSync()
Mikkel Nygaard Ravn61c71712018-05-08 08:02:39 +0200350 ..writeAsStringSync('Existing Podfile');
Sigurd Meldgaard2d3a5c72018-07-20 08:00:30 +0200351 projectUnderTest.ios.podManifestLock
xster4d2c2aa2017-12-27 07:30:31 -0800352 ..createSync(recursive: true)
Mikkel Nygaard Ravn61c71712018-05-08 08:02:39 +0200353 ..writeAsStringSync('Existing lock file.');
Chris Brackencdbdafa2018-05-03 19:40:16 -0700354 final bool didInstall = await cocoaPodsUnderTest.processPods(
stuartmorgan3ebebeb2019-05-31 13:19:44 -0700355 xcodeProject: projectUnderTest.ios,
356 engineDir: 'engine/path',
Chris Brackencdbdafa2018-05-03 19:40:16 -0700357 dependenciesChanged: false,
xster4d2c2aa2017-12-27 07:30:31 -0800358 );
Chris Brackencdbdafa2018-05-03 19:40:16 -0700359 expect(didInstall, isTrue);
xster4d2c2aa2017-12-27 07:30:31 -0800360 verify(mockProcessManager.run(
361 <String>['pod', 'install', '--verbose'],
362 workingDirectory: 'project/ios',
363 environment: <String, String>{'FLUTTER_FRAMEWORK_DIR': 'engine/path', 'COCOAPODS_DISABLE_STATS': 'true'},
364 ));
Mikkel Nygaard Ravn20004352018-02-16 10:17:28 +0100365 }, overrides: <Type, Generator>{
xster4d2c2aa2017-12-27 07:30:31 -0800366 FileSystem: () => fs,
367 ProcessManager: () => mockProcessManager,
Mikkel Nygaard Ravn20004352018-02-16 10:17:28 +0100368 });
xster4d2c2aa2017-12-27 07:30:31 -0800369
Mikkel Nygaard Ravn20004352018-02-16 10:17:28 +0100370 testUsingContext('runs pod install, if Manifest.lock is missing', () async {
Sigurd Meldgaard2d3a5c72018-07-20 08:00:30 +0200371 projectUnderTest.ios.podfile
xster4d2c2aa2017-12-27 07:30:31 -0800372 ..createSync()
Mikkel Nygaard Ravn61c71712018-05-08 08:02:39 +0200373 ..writeAsStringSync('Existing Podfile');
Sigurd Meldgaard2d3a5c72018-07-20 08:00:30 +0200374 projectUnderTest.ios.podfileLock
xster4d2c2aa2017-12-27 07:30:31 -0800375 ..createSync()
Mikkel Nygaard Ravn61c71712018-05-08 08:02:39 +0200376 ..writeAsStringSync('Existing lock file.');
Chris Brackencdbdafa2018-05-03 19:40:16 -0700377 final bool didInstall = await cocoaPodsUnderTest.processPods(
stuartmorgan3ebebeb2019-05-31 13:19:44 -0700378 xcodeProject: projectUnderTest.ios,
379 engineDir: 'engine/path',
Chris Brackencdbdafa2018-05-03 19:40:16 -0700380 dependenciesChanged: false,
Mikkel Nygaard Ravnb3e49762018-02-15 22:17:12 +0100381 );
Chris Brackencdbdafa2018-05-03 19:40:16 -0700382 expect(didInstall, isTrue);
Mikkel Nygaard Ravn20004352018-02-16 10:17:28 +0100383 verify(mockProcessManager.run(
Mikkel Nygaard Ravnc2e1bc02018-02-15 22:55:36 +0100384 <String>['pod', 'install', '--verbose'],
385 workingDirectory: 'project/ios',
Mikkel Nygaard Ravn20004352018-02-16 10:17:28 +0100386 environment: <String, String>{
387 'FLUTTER_FRAMEWORK_DIR': 'engine/path',
388 'COCOAPODS_DISABLE_STATS': 'true',
389 },
Mikkel Nygaard Ravnb3e49762018-02-15 22:17:12 +0100390 ));
Mikkel Nygaard Ravn20004352018-02-16 10:17:28 +0100391 }, overrides: <Type, Generator>{
Mikkel Nygaard Ravnb3e49762018-02-15 22:17:12 +0100392 FileSystem: () => fs,
393 ProcessManager: () => mockProcessManager,
Mikkel Nygaard Ravn20004352018-02-16 10:17:28 +0100394 });
395
396 testUsingContext('runs pod install, if Manifest.lock different from Podspec.lock', () async {
Sigurd Meldgaard2d3a5c72018-07-20 08:00:30 +0200397 projectUnderTest.ios.podfile
Mikkel Nygaard Ravn20004352018-02-16 10:17:28 +0100398 ..createSync()
Mikkel Nygaard Ravn61c71712018-05-08 08:02:39 +0200399 ..writeAsStringSync('Existing Podfile');
Sigurd Meldgaard2d3a5c72018-07-20 08:00:30 +0200400 projectUnderTest.ios.podfileLock
Mikkel Nygaard Ravn20004352018-02-16 10:17:28 +0100401 ..createSync()
Mikkel Nygaard Ravn61c71712018-05-08 08:02:39 +0200402 ..writeAsStringSync('Existing lock file.');
Sigurd Meldgaard2d3a5c72018-07-20 08:00:30 +0200403 projectUnderTest.ios.podManifestLock
Mikkel Nygaard Ravn20004352018-02-16 10:17:28 +0100404 ..createSync(recursive: true)
Mikkel Nygaard Ravn61c71712018-05-08 08:02:39 +0200405 ..writeAsStringSync('Different lock file.');
Chris Brackencdbdafa2018-05-03 19:40:16 -0700406 final bool didInstall = await cocoaPodsUnderTest.processPods(
stuartmorgan3ebebeb2019-05-31 13:19:44 -0700407 xcodeProject: projectUnderTest.ios,
408 engineDir: 'engine/path',
Chris Brackencdbdafa2018-05-03 19:40:16 -0700409 dependenciesChanged: false,
Mikkel Nygaard Ravn20004352018-02-16 10:17:28 +0100410 );
Chris Brackencdbdafa2018-05-03 19:40:16 -0700411 expect(didInstall, isTrue);
Mikkel Nygaard Ravn20004352018-02-16 10:17:28 +0100412 verify(mockProcessManager.run(
413 <String>['pod', 'install', '--verbose'],
414 workingDirectory: 'project/ios',
415 environment: <String, String>{
416 'FLUTTER_FRAMEWORK_DIR': 'engine/path',
417 'COCOAPODS_DISABLE_STATS': 'true',
418 },
419 ));
420 }, overrides: <Type, Generator>{
421 FileSystem: () => fs,
422 ProcessManager: () => mockProcessManager,
423 });
424
425 testUsingContext('runs pod install, if flutter framework changed', () async {
Sigurd Meldgaard2d3a5c72018-07-20 08:00:30 +0200426 projectUnderTest.ios.podfile
Mikkel Nygaard Ravn20004352018-02-16 10:17:28 +0100427 ..createSync()
Mikkel Nygaard Ravn61c71712018-05-08 08:02:39 +0200428 ..writeAsStringSync('Existing Podfile');
Sigurd Meldgaard2d3a5c72018-07-20 08:00:30 +0200429 projectUnderTest.ios.podfileLock
Mikkel Nygaard Ravn20004352018-02-16 10:17:28 +0100430 ..createSync()
Mikkel Nygaard Ravn61c71712018-05-08 08:02:39 +0200431 ..writeAsStringSync('Existing lock file.');
Sigurd Meldgaard2d3a5c72018-07-20 08:00:30 +0200432 projectUnderTest.ios.podManifestLock
Mikkel Nygaard Ravn20004352018-02-16 10:17:28 +0100433 ..createSync(recursive: true)
Mikkel Nygaard Ravn61c71712018-05-08 08:02:39 +0200434 ..writeAsStringSync('Existing lock file.');
Chris Brackencdbdafa2018-05-03 19:40:16 -0700435 final bool didInstall = await cocoaPodsUnderTest.processPods(
stuartmorgan3ebebeb2019-05-31 13:19:44 -0700436 xcodeProject: projectUnderTest.ios,
437 engineDir: 'engine/path',
Chris Brackencdbdafa2018-05-03 19:40:16 -0700438 dependenciesChanged: true,
Mikkel Nygaard Ravn20004352018-02-16 10:17:28 +0100439 );
Chris Brackencdbdafa2018-05-03 19:40:16 -0700440 expect(didInstall, isTrue);
Mikkel Nygaard Ravn20004352018-02-16 10:17:28 +0100441 verify(mockProcessManager.run(
442 <String>['pod', 'install', '--verbose'],
443 workingDirectory: 'project/ios',
444 environment: <String, String>{
445 'FLUTTER_FRAMEWORK_DIR': 'engine/path',
446 'COCOAPODS_DISABLE_STATS': 'true',
447 },
448 ));
449 }, overrides: <Type, Generator>{
450 FileSystem: () => fs,
451 ProcessManager: () => mockProcessManager,
452 });
453
Mikkel Nygaard Ravn61c71712018-05-08 08:02:39 +0200454 testUsingContext('runs pod install, if Podfile.lock is older than Podfile', () async {
Sigurd Meldgaard2d3a5c72018-07-20 08:00:30 +0200455 projectUnderTest.ios.podfile
Mikkel Nygaard Ravn61c71712018-05-08 08:02:39 +0200456 ..createSync()
457 ..writeAsStringSync('Existing Podfile');
Sigurd Meldgaard2d3a5c72018-07-20 08:00:30 +0200458 projectUnderTest.ios.podfileLock
Mikkel Nygaard Ravn61c71712018-05-08 08:02:39 +0200459 ..createSync()
460 ..writeAsStringSync('Existing lock file.');
Sigurd Meldgaard2d3a5c72018-07-20 08:00:30 +0200461 projectUnderTest.ios.podManifestLock
Mikkel Nygaard Ravn61c71712018-05-08 08:02:39 +0200462 ..createSync(recursive: true)
463 ..writeAsStringSync('Existing lock file.');
Alexandre Ardhuind927c932018-09-12 08:29:29 +0200464 await Future<void>.delayed(const Duration(milliseconds: 10));
Sigurd Meldgaard2d3a5c72018-07-20 08:00:30 +0200465 projectUnderTest.ios.podfile
Mikkel Nygaard Ravn61c71712018-05-08 08:02:39 +0200466 ..writeAsStringSync('Updated Podfile');
467 await cocoaPodsUnderTest.processPods(
stuartmorgan3ebebeb2019-05-31 13:19:44 -0700468 xcodeProject: projectUnderTest.ios,
469 engineDir: 'engine/path',
Mikkel Nygaard Ravn61c71712018-05-08 08:02:39 +0200470 dependenciesChanged: false,
471 );
472 verify(mockProcessManager.run(
473 <String>['pod', 'install', '--verbose'],
474 workingDirectory: 'project/ios',
475 environment: <String, String>{
476 'FLUTTER_FRAMEWORK_DIR': 'engine/path',
477 'COCOAPODS_DISABLE_STATS': 'true',
478 },
479 ));
480 }, overrides: <Type, Generator>{
481 FileSystem: () => fs,
482 ProcessManager: () => mockProcessManager,
483 });
484
Mikkel Nygaard Ravn20004352018-02-16 10:17:28 +0100485 testUsingContext('skips pod install, if nothing changed', () async {
Sigurd Meldgaard2d3a5c72018-07-20 08:00:30 +0200486 projectUnderTest.ios.podfile
Mikkel Nygaard Ravn20004352018-02-16 10:17:28 +0100487 ..createSync()
Mikkel Nygaard Ravn61c71712018-05-08 08:02:39 +0200488 ..writeAsStringSync('Existing Podfile');
Sigurd Meldgaard2d3a5c72018-07-20 08:00:30 +0200489 projectUnderTest.ios.podfileLock
Mikkel Nygaard Ravn20004352018-02-16 10:17:28 +0100490 ..createSync()
Mikkel Nygaard Ravn61c71712018-05-08 08:02:39 +0200491 ..writeAsStringSync('Existing lock file.');
Sigurd Meldgaard2d3a5c72018-07-20 08:00:30 +0200492 projectUnderTest.ios.podManifestLock
Mikkel Nygaard Ravn20004352018-02-16 10:17:28 +0100493 ..createSync(recursive: true)
Mikkel Nygaard Ravn61c71712018-05-08 08:02:39 +0200494 ..writeAsStringSync('Existing lock file.');
Chris Brackencdbdafa2018-05-03 19:40:16 -0700495 final bool didInstall = await cocoaPodsUnderTest.processPods(
stuartmorgan3ebebeb2019-05-31 13:19:44 -0700496 xcodeProject: projectUnderTest.ios,
497 engineDir: 'engine/path',
Chris Brackencdbdafa2018-05-03 19:40:16 -0700498 dependenciesChanged: false,
Mikkel Nygaard Ravn20004352018-02-16 10:17:28 +0100499 );
Chris Brackencdbdafa2018-05-03 19:40:16 -0700500 expect(didInstall, isFalse);
Mikkel Nygaard Ravn20004352018-02-16 10:17:28 +0100501 verifyNever(mockProcessManager.run(
Sam Rawlins9f8a70b2018-06-21 16:23:47 -0700502 argThat(containsAllInOrder(<String>['pod', 'install'])),
Sam Rawlinsfba81d02018-05-31 08:24:26 -0700503 workingDirectory: anyNamed('workingDirectory'),
Sam Rawlins1f76f7f2018-05-16 10:19:05 -0700504 environment: anyNamed('environment'),
Mikkel Nygaard Ravn20004352018-02-16 10:17:28 +0100505 ));
506 }, overrides: <Type, Generator>{
507 FileSystem: () => fs,
508 ProcessManager: () => mockProcessManager,
509 });
xsterf7f16852018-02-16 16:05:16 -0800510
511 testUsingContext('a failed pod install deletes Pods/Manifest.lock', () async {
Sigurd Meldgaard2d3a5c72018-07-20 08:00:30 +0200512 projectUnderTest.ios.podfile
xsterf7f16852018-02-16 16:05:16 -0800513 ..createSync()
Mikkel Nygaard Ravn61c71712018-05-08 08:02:39 +0200514 ..writeAsStringSync('Existing Podfile');
Sigurd Meldgaard2d3a5c72018-07-20 08:00:30 +0200515 projectUnderTest.ios.podfileLock
xsterf7f16852018-02-16 16:05:16 -0800516 ..createSync()
Mikkel Nygaard Ravn61c71712018-05-08 08:02:39 +0200517 ..writeAsStringSync('Existing lock file.');
Sigurd Meldgaard2d3a5c72018-07-20 08:00:30 +0200518 projectUnderTest.ios.podManifestLock
xsterf7f16852018-02-16 16:05:16 -0800519 ..createSync(recursive: true)
Mikkel Nygaard Ravn61c71712018-05-08 08:02:39 +0200520 ..writeAsStringSync('Existing lock file.');
xsterf7f16852018-02-16 16:05:16 -0800521
522 when(mockProcessManager.run(
523 <String>['pod', 'install', '--verbose'],
524 workingDirectory: 'project/ios',
525 environment: <String, String>{
526 'FLUTTER_FRAMEWORK_DIR': 'engine/path',
527 'COCOAPODS_DISABLE_STATS': 'true',
528 },
Matan Lurey81070892018-03-19 11:45:44 -0700529 )).thenAnswer(
Mikkel Nygaard Ravn61c71712018-05-08 08:02:39 +0200530 (_) async => exitsWithError()
Matan Lurey81070892018-03-19 11:45:44 -0700531 );
xsterf7f16852018-02-16 16:05:16 -0800532
533 try {
534 await cocoaPodsUnderTest.processPods(
stuartmorgan3ebebeb2019-05-31 13:19:44 -0700535 xcodeProject: projectUnderTest.ios,
536 engineDir: 'engine/path',
Chris Brackencdbdafa2018-05-03 19:40:16 -0700537 dependenciesChanged: true,
xsterf7f16852018-02-16 16:05:16 -0800538 );
539 fail('Tool throw expected when pod install fails');
540 } on ToolExit {
Sigurd Meldgaard2d3a5c72018-07-20 08:00:30 +0200541 expect(projectUnderTest.ios.podManifestLock.existsSync(), isFalse);
xsterf7f16852018-02-16 16:05:16 -0800542 }
543 }, overrides: <Type, Generator>{
544 FileSystem: () => fs,
545 ProcessManager: () => mockProcessManager,
546 });
Mikkel Nygaard Ravn20004352018-02-16 10:17:28 +0100547 });
Dan Field704814c2019-02-05 16:03:37 -0800548
549 group('Pods repos dir is custom', () {
550 String cocoapodsRepoDir;
551 Map<String, String> environment;
552 setUp(() {
553 cocoapodsRepoDir = podsIsInCustomDir();
554 environment = <String, String>{
555 'FLUTTER_FRAMEWORK_DIR': 'engine/path',
556 'COCOAPODS_DISABLE_STATS': 'true',
557 'CP_REPOS_DIR': cocoapodsRepoDir,
558 };
559 });
560
561 testUsingContext('succeeds, if specs repo is in CP_REPOS_DIR.', () async {
562 fs.file(fs.path.join('project', 'ios', 'Podfile'))
563 ..createSync()
564 ..writeAsStringSync('Existing Podfile');
565
566 when(mockProcessManager.run(
567 <String>['pod', 'install', '--verbose'],
568 workingDirectory: 'project/ios',
569 environment: environment,
570 )).thenAnswer((_) async => exitsHappy());
571 final bool success = await cocoaPodsUnderTest.processPods(
stuartmorgan3ebebeb2019-05-31 13:19:44 -0700572 xcodeProject: projectUnderTest.ios,
573 engineDir: 'engine/path',
Dan Field704814c2019-02-05 16:03:37 -0800574 );
575 expect(success, true);
576 }, overrides: <Type, Generator>{
577 FileSystem: () => fs,
578 ProcessManager: () => mockProcessManager,
579 Platform: () => FakePlatform(environment: environment),
580 });
581 });
xster6a494192017-07-12 18:35:08 -0700582}
583
584class MockProcessManager extends Mock implements ProcessManager {}
Mikkel Nygaard Ravn20004352018-02-16 10:17:28 +0100585class MockXcodeProjectInterpreter extends Mock implements XcodeProjectInterpreter {}
xster6a494192017-07-12 18:35:08 -0700586
Alexandre Ardhuin5169ab52019-02-21 09:27:07 +0100587ProcessResult exitsWithError([ String stdout = '' ]) => ProcessResult(1, 1, stdout, '');
588ProcessResult exitsHappy([ String stdout = '' ]) => ProcessResult(1, 0, stdout, '');