xster | 6a49419 | 2017-07-12 18:35:08 -0700 | [diff] [blame] | 1 | // 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 | |
| 5 | import 'dart:async'; |
| 6 | |
| 7 | import 'package:file/file.dart'; |
| 8 | import 'package:file/memory.dart'; |
| 9 | import 'package:flutter_tools/src/base/io.dart'; |
| 10 | import 'package:flutter_tools/src/ios/cocoapods.dart'; |
| 11 | import 'package:flutter_tools/src/cache.dart'; |
| 12 | import 'package:mockito/mockito.dart'; |
| 13 | import 'package:process/process.dart'; |
| 14 | import 'package:test/test.dart'; |
| 15 | |
| 16 | import '../src/context.dart'; |
| 17 | |
| 18 | void 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', |
xster | 9275083 | 2017-07-12 19:15:54 -0700 | [diff] [blame] | 44 | environment: <String, String>{'FLUTTER_FRAMEWORK_DIR': 'engine/path', 'COCOAPODS_DISABLE_STATS': 'true'}, |
xster | 6a49419 | 2017-07-12 18:35:08 -0700 | [diff] [blame] | 45 | )).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', |
xster | 9275083 | 2017-07-12 19:15:54 -0700 | [diff] [blame] | 59 | environment: <String, String>{'FLUTTER_FRAMEWORK_DIR': 'engine/path', 'COCOAPODS_DISABLE_STATS': 'true'}, |
xster | 6a49419 | 2017-07-12 18:35:08 -0700 | [diff] [blame] | 60 | )); |
| 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', |
xster | 9275083 | 2017-07-12 19:15:54 -0700 | [diff] [blame] | 80 | environment: <String, String>{'FLUTTER_FRAMEWORK_DIR': 'engine/path', 'COCOAPODS_DISABLE_STATS': 'true'}, |
xster | 6a49419 | 2017-07-12 18:35:08 -0700 | [diff] [blame] | 81 | )); |
| 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', |
xster | 9275083 | 2017-07-12 19:15:54 -0700 | [diff] [blame] | 102 | environment: <String, String>{'FLUTTER_FRAMEWORK_DIR': 'engine/path', 'COCOAPODS_DISABLE_STATS': 'true'}, |
xster | 6a49419 | 2017-07-12 18:35:08 -0700 | [diff] [blame] | 103 | )); |
| 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', |
xster | 9275083 | 2017-07-12 19:15:54 -0700 | [diff] [blame] | 125 | environment: <String, String>{'FLUTTER_FRAMEWORK_DIR': 'engine/path', 'COCOAPODS_DISABLE_STATS': 'true'}, |
xster | 6a49419 | 2017-07-12 18:35:08 -0700 | [diff] [blame] | 126 | )); |
| 127 | } |
| 128 | }, |
| 129 | overrides: <Type, Generator>{ |
| 130 | FileSystem: () => fs, |
| 131 | ProcessManager: () => mockProcessManager, |
| 132 | }, |
| 133 | ); |
xster | e940381 | 2017-11-10 12:41:58 -0800 | [diff] [blame^] | 134 | |
| 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 | |
| 155 | None of your spec sources contain a spec satisfying the dependencies: `Firebase/Auth, Firebase/Auth (= 4.0.0)`. |
| 156 | |
| 157 | You 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 | |
| 162 | Note: 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 | ); |
xster | 6a49419 | 2017-07-12 18:35:08 -0700 | [diff] [blame] | 180 | } |
| 181 | |
| 182 | class MockProcessManager extends Mock implements ProcessManager {} |
| 183 | |
| 184 | class 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 | |
| 199 | final ProcessResult exitsHappy = new ProcessResult( |
| 200 | 1, // pid |
| 201 | 0, // exitCode |
| 202 | '', // stdout |
| 203 | '', // stderr |
| 204 | ); |