blob: 493468fae8edabfb3c935e74e34a4e5da1c487bb [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';
9import 'package:flutter_tools/src/base/io.dart';
10import 'package:flutter_tools/src/ios/cocoapods.dart';
11import 'package:flutter_tools/src/cache.dart';
12import 'package:mockito/mockito.dart';
13import 'package:process/process.dart';
14import 'package:test/test.dart';
15
16import '../src/context.dart';
17
18void main() {
19 FileSystem fs;
20 ProcessManager mockProcessManager;
21 Directory projectUnderTest;
22 CocoaPods cocoaPodsUnderTest;
23
24 setUp(() {
25 Cache.flutterRoot = 'flutter';
26 fs = new MemoryFileSystem();
27 mockProcessManager = new MockProcessManager();
28 projectUnderTest = fs.directory(fs.path.join('project', 'ios'))..createSync(recursive: true);
29 fs.file(fs.path.join(
30 Cache.flutterRoot, 'packages', 'flutter_tools', 'templates', 'cocoapods', 'Podfile-objc'
31 ))
32 ..createSync(recursive: true)
33 ..writeAsStringSync('Objective-C podfile template');
34 fs.file(fs.path.join(
35 Cache.flutterRoot, 'packages', 'flutter_tools', 'templates', 'cocoapods', 'Podfile-swift'
36 ))
37 ..createSync(recursive: true)
38 ..writeAsStringSync('Swift podfile template');
39 cocoaPodsUnderTest = const TestCocoaPods();
40
41 when(mockProcessManager.run(
42 <String>['pod', 'install', '--verbose'],
43 workingDirectory: 'project/ios',
xster92750832017-07-12 19:15:54 -070044 environment: <String, String>{'FLUTTER_FRAMEWORK_DIR': 'engine/path', 'COCOAPODS_DISABLE_STATS': 'true'},
xster6a494192017-07-12 18:35:08 -070045 )).thenReturn(exitsHappy);
46 });
47
48 testUsingContext(
49 'create objective-c Podfile when not present',
50 () async {
51 await cocoaPodsUnderTest.processPods(
52 appIosDir: projectUnderTest,
53 iosEngineDir: 'engine/path',
54 );
55 expect(fs.file(fs.path.join('project', 'ios', 'Podfile')).readAsStringSync() , 'Objective-C podfile template');
56 verify(mockProcessManager.run(
57 <String>['pod', 'install', '--verbose'],
58 workingDirectory: 'project/ios',
xster92750832017-07-12 19:15:54 -070059 environment: <String, String>{'FLUTTER_FRAMEWORK_DIR': 'engine/path', 'COCOAPODS_DISABLE_STATS': 'true'},
xster6a494192017-07-12 18:35:08 -070060 ));
61 },
62 overrides: <Type, Generator>{
63 FileSystem: () => fs,
64 ProcessManager: () => mockProcessManager,
65 },
66 );
67
68 testUsingContext(
69 'create swift Podfile if swift',
70 () async {
71 await cocoaPodsUnderTest.processPods(
72 appIosDir: projectUnderTest,
73 iosEngineDir: 'engine/path',
74 isSwift: true,
75 );
76 expect(fs.file(fs.path.join('project', 'ios', 'Podfile')).readAsStringSync() , 'Swift podfile template');
77 verify(mockProcessManager.run(
78 <String>['pod', 'install', '--verbose'],
79 workingDirectory: 'project/ios',
xster92750832017-07-12 19:15:54 -070080 environment: <String, String>{'FLUTTER_FRAMEWORK_DIR': 'engine/path', 'COCOAPODS_DISABLE_STATS': 'true'},
xster6a494192017-07-12 18:35:08 -070081 ));
82 },
83 overrides: <Type, Generator>{
84 FileSystem: () => fs,
85 ProcessManager: () => mockProcessManager,
86 },
87 );
88
89 testUsingContext(
90 'do not recreate Podfile when present',
91 () async {
92 fs.file(fs.path.join('project', 'ios', 'Podfile'))
93 ..createSync()
94 ..writeAsString('Existing Podfile');
95 await cocoaPodsUnderTest.processPods(
96 appIosDir: projectUnderTest,
97 iosEngineDir: 'engine/path',
98 ); expect(fs.file(fs.path.join('project', 'ios', 'Podfile')).readAsStringSync() , 'Existing Podfile');
99 verify(mockProcessManager.run(
100 <String>['pod', 'install', '--verbose'],
101 workingDirectory: 'project/ios',
xster92750832017-07-12 19:15:54 -0700102 environment: <String, String>{'FLUTTER_FRAMEWORK_DIR': 'engine/path', 'COCOAPODS_DISABLE_STATS': 'true'},
xster6a494192017-07-12 18:35:08 -0700103 ));
104 },
105 overrides: <Type, Generator>{
106 FileSystem: () => fs,
107 ProcessManager: () => mockProcessManager,
108 },
109 );
110
111 testUsingContext(
112 'missing CocoaPods throws',
113 () async {
114 cocoaPodsUnderTest = const TestCocoaPods(false);
115 try {
116 await cocoaPodsUnderTest.processPods(
117 appIosDir: projectUnderTest,
118 iosEngineDir: 'engine/path',
119 );
120 fail('Expected tool error');
121 } catch (ToolExit) {
122 verifyNever(mockProcessManager.run(
123 <String>['pod', 'install', '--verbose'],
124 workingDirectory: 'project/ios',
xster92750832017-07-12 19:15:54 -0700125 environment: <String, String>{'FLUTTER_FRAMEWORK_DIR': 'engine/path', 'COCOAPODS_DISABLE_STATS': 'true'},
xster6a494192017-07-12 18:35:08 -0700126 ));
127 }
128 },
129 overrides: <Type, Generator>{
130 FileSystem: () => fs,
131 ProcessManager: () => mockProcessManager,
132 },
133 );
xstere9403812017-11-10 12:41:58 -0800134
135 testUsingContext(
136 'outdated specs repo should print error',
137 () async {
138 fs.file(fs.path.join('project', 'ios', 'Podfile'))
139 ..createSync()
140 ..writeAsString('Existing Podfile');
141
142 when(mockProcessManager.run(
143 <String>['pod', 'install', '--verbose'],
144 workingDirectory: 'project/ios',
145 environment: <String, String>{'FLUTTER_FRAMEWORK_DIR': 'engine/path', 'COCOAPODS_DISABLE_STATS': 'true'},
146 )).thenReturn(new ProcessResult(
147 1,
148 1,
149 '''
150[!] Unable to satisfy the following requirements:
151
152- `Firebase/Auth` required by `Podfile`
153- `Firebase/Auth (= 4.0.0)` required by `Podfile.lock`
154
155None of your spec sources contain a spec satisfying the dependencies: `Firebase/Auth, Firebase/Auth (= 4.0.0)`.
156
157You have either:
158 * out-of-date source repos which you can update with `pod repo update` or with `pod install --repo-update`.
159 * mistyped the name or version.
160 * not added the source repo that hosts the Podspec to your Podfile.
161
162Note: as of CocoaPods 1.0, `pod repo update` does not happen on `pod install` by default.''',
163 '',
164 ));
165 try {
166 await cocoaPodsUnderTest.processPods(
167 appIosDir: projectUnderTest,
168 iosEngineDir: 'engine/path',
169 ); expect(fs.file(fs.path.join('project', 'ios', 'Podfile')).readAsStringSync() , 'Existing Podfile');
170 fail('Exception expected');
171 } catch (ToolExit) {
172 expect(testLogger.errorText, contains("CocoaPods's specs repository is too out-of-date to satisfy dependencies"));
173 }
174 },
175 overrides: <Type, Generator>{
176 FileSystem: () => fs,
177 ProcessManager: () => mockProcessManager,
178 },
179 );
xster6a494192017-07-12 18:35:08 -0700180}
181
182class MockProcessManager extends Mock implements ProcessManager {}
183
184class TestCocoaPods extends CocoaPods {
185 const TestCocoaPods([this._hasCocoaPods = true]);
186
187 final bool _hasCocoaPods;
188
189 @override
190 Future<bool> get hasCocoaPods => new Future<bool>.value(_hasCocoaPods);
191
192 @override
193 Future<String> get cocoaPodsVersionText async => new Future<String>.value('1.5.0');
194
195 @override
196 Future<bool> get isCocoaPodsInitialized => new Future<bool>.value(true);
197}
198
199final ProcessResult exitsHappy = new ProcessResult(
200 1, // pid
201 0, // exitCode
202 '', // stdout
203 '', // stderr
204);