2017-07-13 01:35:08 +00:00
|
|
|
// 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';
|
2018-02-15 21:17:12 +00:00
|
|
|
import 'package:flutter_tools/src/ios/cocoapods.dart';
|
2018-02-15 21:55:36 +00:00
|
|
|
import 'package:flutter_tools/src/cache.dart';
|
2017-07-13 01:35:08 +00:00
|
|
|
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',
|
2017-12-27 10:51:44 +00:00
|
|
|
environment: <String, String>{'FLUTTER_FRAMEWORK_DIR': 'engine/path', 'COCOAPODS_DISABLE_STATS': 'true'},
|
2017-07-13 01:35:08 +00:00
|
|
|
)).thenReturn(exitsHappy);
|
|
|
|
});
|
|
|
|
|
2018-02-15 21:55:36 +00:00
|
|
|
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', 'COCOAPODS_DISABLE_STATS': 'true'},
|
|
|
|
));
|
|
|
|
},
|
|
|
|
overrides: <Type, Generator>{
|
2018-02-15 21:17:12 +00:00
|
|
|
FileSystem: () => fs,
|
2018-02-15 21:55:36 +00:00
|
|
|
ProcessManager: () => mockProcessManager,
|
|
|
|
},
|
|
|
|
);
|
2018-02-15 21:17:12 +00:00
|
|
|
|
2018-02-15 21:55:36 +00:00
|
|
|
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', 'COCOAPODS_DISABLE_STATS': 'true'},
|
|
|
|
));
|
|
|
|
},
|
|
|
|
overrides: <Type, Generator>{
|
2018-02-15 21:17:12 +00:00
|
|
|
FileSystem: () => fs,
|
2018-02-15 21:55:36 +00:00
|
|
|
ProcessManager: () => mockProcessManager,
|
|
|
|
},
|
|
|
|
);
|
2018-02-15 21:17:12 +00:00
|
|
|
|
2018-02-15 21:55:36 +00:00
|
|
|
testUsingContext(
|
|
|
|
'do not recreate Podfile when present',
|
|
|
|
() async {
|
|
|
|
fs.file(fs.path.join('project', 'ios', 'Podfile'))
|
|
|
|
..createSync()
|
|
|
|
..writeAsString('Existing Podfile');
|
2017-07-13 01:35:08 +00:00
|
|
|
await cocoaPodsUnderTest.processPods(
|
|
|
|
appIosDir: projectUnderTest,
|
2017-12-27 10:51:44 +00:00
|
|
|
iosEngineDir: 'engine/path',
|
2017-12-27 15:30:31 +00:00
|
|
|
);
|
2018-02-15 21:55:36 +00:00
|
|
|
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', 'COCOAPODS_DISABLE_STATS': 'true'},
|
2017-07-13 01:35:08 +00:00
|
|
|
));
|
2018-02-15 21:55:36 +00:00
|
|
|
},
|
|
|
|
overrides: <Type, Generator>{
|
2017-07-13 01:35:08 +00:00
|
|
|
FileSystem: () => fs,
|
|
|
|
ProcessManager: () => mockProcessManager,
|
2018-02-15 21:55:36 +00:00
|
|
|
},
|
|
|
|
);
|
2017-07-13 01:35:08 +00:00
|
|
|
|
2018-02-15 21:55:36 +00:00
|
|
|
testUsingContext(
|
|
|
|
'missing CocoaPods throws',
|
|
|
|
() async {
|
|
|
|
cocoaPodsUnderTest = const TestCocoaPods(false);
|
2017-07-13 01:35:08 +00:00
|
|
|
try {
|
|
|
|
await cocoaPodsUnderTest.processPods(
|
|
|
|
appIosDir: projectUnderTest,
|
2017-12-27 10:51:44 +00:00
|
|
|
iosEngineDir: 'engine/path',
|
2017-07-13 01:35:08 +00:00
|
|
|
);
|
2018-02-15 21:55:36 +00:00
|
|
|
fail('Expected tool error');
|
|
|
|
} catch (ToolExit) {
|
2017-07-13 01:35:08 +00:00
|
|
|
verifyNever(mockProcessManager.run(
|
2018-02-15 21:55:36 +00:00
|
|
|
<String>['pod', 'install', '--verbose'],
|
|
|
|
workingDirectory: 'project/ios',
|
|
|
|
environment: <String, String>{'FLUTTER_FRAMEWORK_DIR': 'engine/path', 'COCOAPODS_DISABLE_STATS': 'true'},
|
2017-07-13 01:35:08 +00:00
|
|
|
));
|
|
|
|
}
|
2018-02-15 21:55:36 +00:00
|
|
|
},
|
|
|
|
overrides: <Type, Generator>{
|
2017-07-13 01:35:08 +00:00
|
|
|
FileSystem: () => fs,
|
|
|
|
ProcessManager: () => mockProcessManager,
|
2018-02-15 21:55:36 +00:00
|
|
|
},
|
|
|
|
);
|
2017-11-10 20:41:58 +00:00
|
|
|
|
2018-02-15 21:55:36 +00:00
|
|
|
testUsingContext(
|
|
|
|
'outdated specs repo should print error',
|
|
|
|
() async {
|
2017-11-10 20:41:58 +00:00
|
|
|
fs.file(fs.path.join('project', 'ios', 'Podfile'))
|
|
|
|
..createSync()
|
|
|
|
..writeAsString('Existing Podfile');
|
|
|
|
|
|
|
|
when(mockProcessManager.run(
|
|
|
|
<String>['pod', 'install', '--verbose'],
|
|
|
|
workingDirectory: 'project/ios',
|
2018-02-15 21:55:36 +00:00
|
|
|
environment: <String, String>{'FLUTTER_FRAMEWORK_DIR': 'engine/path', 'COCOAPODS_DISABLE_STATS': 'true'},
|
2017-11-10 20:41:58 +00:00
|
|
|
)).thenReturn(new ProcessResult(
|
|
|
|
1,
|
|
|
|
1,
|
|
|
|
'''
|
|
|
|
[!] Unable to satisfy the following requirements:
|
|
|
|
|
|
|
|
- `Firebase/Auth` required by `Podfile`
|
|
|
|
- `Firebase/Auth (= 4.0.0)` required by `Podfile.lock`
|
|
|
|
|
|
|
|
None of your spec sources contain a spec satisfying the dependencies: `Firebase/Auth, Firebase/Auth (= 4.0.0)`.
|
|
|
|
|
|
|
|
You have either:
|
|
|
|
* out-of-date source repos which you can update with `pod repo update` or with `pod install --repo-update`.
|
|
|
|
* mistyped the name or version.
|
|
|
|
* not added the source repo that hosts the Podspec to your Podfile.
|
|
|
|
|
|
|
|
Note: as of CocoaPods 1.0, `pod repo update` does not happen on `pod install` by default.''',
|
|
|
|
'',
|
|
|
|
));
|
|
|
|
try {
|
|
|
|
await cocoaPodsUnderTest.processPods(
|
|
|
|
appIosDir: projectUnderTest,
|
2017-12-27 10:51:44 +00:00
|
|
|
iosEngineDir: 'engine/path',
|
2018-02-15 21:55:36 +00:00
|
|
|
); expect(fs.file(fs.path.join('project', 'ios', 'Podfile')).readAsStringSync() , 'Existing Podfile');
|
|
|
|
fail('Exception expected');
|
|
|
|
} catch (ToolExit) {
|
|
|
|
expect(testLogger.errorText, contains("CocoaPods's specs repository is too out-of-date to satisfy dependencies"));
|
2017-11-10 20:41:58 +00:00
|
|
|
}
|
2018-02-15 21:55:36 +00:00
|
|
|
},
|
|
|
|
overrides: <Type, Generator>{
|
2017-11-10 20:41:58 +00:00
|
|
|
FileSystem: () => fs,
|
|
|
|
ProcessManager: () => mockProcessManager,
|
2018-02-15 21:55:36 +00:00
|
|
|
},
|
|
|
|
);
|
2017-12-27 15:30:31 +00:00
|
|
|
|
2018-02-15 21:55:36 +00:00
|
|
|
testUsingContext(
|
|
|
|
'Run pod install if plugins or flutter framework have changes.',
|
|
|
|
() async {
|
|
|
|
fs.file(fs.path.join('project', 'ios', 'Podfile'))
|
2017-12-27 15:30:31 +00:00
|
|
|
..createSync()
|
|
|
|
..writeAsString('Existing Podfile');
|
2018-02-15 21:55:36 +00:00
|
|
|
fs.file(fs.path.join('project', 'ios', 'Podfile.lock'))
|
2017-12-27 15:30:31 +00:00
|
|
|
..createSync()
|
2018-02-15 21:55:36 +00:00
|
|
|
..writeAsString('Existing lock files.');
|
|
|
|
fs.file(fs.path.join('project', 'ios', 'Pods','Manifest.lock'))
|
2017-12-27 15:30:31 +00:00
|
|
|
..createSync(recursive: true)
|
2018-02-15 21:55:36 +00:00
|
|
|
..writeAsString('Existing lock files.');
|
2017-12-27 15:30:31 +00:00
|
|
|
await cocoaPodsUnderTest.processPods(
|
2018-02-15 21:55:36 +00:00
|
|
|
appIosDir: projectUnderTest,
|
|
|
|
iosEngineDir: 'engine/path',
|
|
|
|
pluginOrFlutterPodChanged: true
|
2017-12-27 15:30:31 +00:00
|
|
|
);
|
2018-02-15 21:17:12 +00:00
|
|
|
verify(mockProcessManager.run(
|
2017-12-27 15:30:31 +00:00
|
|
|
<String>['pod', 'install', '--verbose'],
|
|
|
|
workingDirectory: 'project/ios',
|
2018-02-15 21:55:36 +00:00
|
|
|
environment: <String, String>{'FLUTTER_FRAMEWORK_DIR': 'engine/path', 'COCOAPODS_DISABLE_STATS': 'true'},
|
2017-12-27 15:30:31 +00:00
|
|
|
));
|
2018-02-15 21:55:36 +00:00
|
|
|
},
|
|
|
|
overrides: <Type, Generator>{
|
2017-12-27 15:30:31 +00:00
|
|
|
FileSystem: () => fs,
|
|
|
|
ProcessManager: () => mockProcessManager,
|
2018-02-15 21:55:36 +00:00
|
|
|
},
|
|
|
|
);
|
2018-02-15 21:17:12 +00:00
|
|
|
|
2018-02-15 21:55:36 +00:00
|
|
|
testUsingContext(
|
|
|
|
'Skip pod install if plugins and flutter framework remain unchanged.',
|
|
|
|
() async {
|
|
|
|
fs.file(fs.path.join('project', 'ios', 'Podfile'))
|
2018-02-15 21:17:12 +00:00
|
|
|
..createSync()
|
|
|
|
..writeAsString('Existing Podfile');
|
2018-02-15 21:55:36 +00:00
|
|
|
fs.file(fs.path.join('project', 'ios', 'Podfile.lock'))
|
2018-02-15 21:17:12 +00:00
|
|
|
..createSync()
|
2018-02-15 21:55:36 +00:00
|
|
|
..writeAsString('Existing lock files.');
|
|
|
|
fs.file(fs.path.join('project', 'ios', 'Pods','Manifest.lock'))
|
2018-02-15 21:17:12 +00:00
|
|
|
..createSync(recursive: true)
|
2018-02-15 21:55:36 +00:00
|
|
|
..writeAsString('Existing lock files.');
|
2018-02-15 21:17:12 +00:00
|
|
|
await cocoaPodsUnderTest.processPods(
|
2018-02-15 21:55:36 +00:00
|
|
|
appIosDir: projectUnderTest,
|
|
|
|
iosEngineDir: 'engine/path',
|
|
|
|
pluginOrFlutterPodChanged: false
|
2018-02-15 21:17:12 +00:00
|
|
|
);
|
2018-02-15 21:55:36 +00:00
|
|
|
verifyNever(mockProcessManager.run(
|
2018-02-15 21:17:12 +00:00
|
|
|
<String>['pod', 'install', '--verbose'],
|
|
|
|
workingDirectory: 'project/ios',
|
2018-02-15 21:55:36 +00:00
|
|
|
environment: <String, String>{'FLUTTER_FRAMEWORK_DIR': 'engine/path', 'COCOAPODS_DISABLE_STATS': 'true'},
|
2018-02-15 21:17:12 +00:00
|
|
|
));
|
2018-02-15 21:55:36 +00:00
|
|
|
},
|
|
|
|
overrides: <Type, Generator>{
|
2018-02-15 21:17:12 +00:00
|
|
|
FileSystem: () => fs,
|
|
|
|
ProcessManager: () => mockProcessManager,
|
2018-02-15 21:55:36 +00:00
|
|
|
},
|
|
|
|
);
|
2017-07-13 01:35:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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(
|
2018-02-02 22:27:29 +00:00
|
|
|
1, // pid
|
|
|
|
0, // exitCode
|
|
|
|
'', // stdout
|
|
|
|
'', // stderr
|
2017-07-13 01:35:08 +00:00
|
|
|
);
|