mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00

* Update project.pbxproj files to say Flutter rather than Chromium Also, the templates now have an empty organization so that we don't cause people to give their apps a Flutter copyright. * Update the copyright notice checker to require a standard notice on all files * Update copyrights on Dart files. (This was a mechanical commit.) * Fix weird license headers on Dart files that deviate from our conventions; relicense Shrine. Some were already marked "The Flutter Authors", not clear why. Their dates have been normalized. Some were missing the blank line after the license. Some were randomly different in trivial ways for no apparent reason (e.g. missing the trailing period). * Clean up the copyrights in non-Dart files. (Manual edits.) Also, make sure templates don't have copyrights. * Fix some more ORGANIZATIONNAMEs
656 lines
25 KiB
Dart
656 lines
25 KiB
Dart
// Copyright 2014 The Flutter 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/common.dart';
|
|
import 'package:flutter_tools/src/base/io.dart';
|
|
import 'package:flutter_tools/src/base/platform.dart';
|
|
import 'package:flutter_tools/src/cache.dart';
|
|
import 'package:flutter_tools/src/ios/xcodeproj.dart';
|
|
import 'package:flutter_tools/src/macos/cocoapods.dart';
|
|
import 'package:flutter_tools/src/plugins.dart';
|
|
import 'package:flutter_tools/src/project.dart';
|
|
import 'package:mockito/mockito.dart';
|
|
import 'package:process/process.dart';
|
|
|
|
import '../../src/common.dart';
|
|
import '../../src/context.dart';
|
|
|
|
typedef InvokeProcess = Future<ProcessResult> Function();
|
|
|
|
void main() {
|
|
FileSystem fs;
|
|
ProcessManager mockProcessManager;
|
|
MockXcodeProjectInterpreter mockXcodeProjectInterpreter;
|
|
FlutterProject projectUnderTest;
|
|
CocoaPods cocoaPodsUnderTest;
|
|
InvokeProcess resultOfPodVersion;
|
|
|
|
void pretendPodVersionFails() {
|
|
resultOfPodVersion = () async => exitsWithError();
|
|
}
|
|
|
|
void pretendPodVersionIs(String versionText) {
|
|
resultOfPodVersion = () async => exitsHappy(versionText);
|
|
}
|
|
|
|
void podsIsInHomeDir() {
|
|
fs.directory(fs.path.join(homeDirPath, '.cocoapods', 'repos', 'master')).createSync(recursive: true);
|
|
}
|
|
|
|
String podsIsInCustomDir({String cocoapodsReposDir}) {
|
|
cocoapodsReposDir ??= fs.path.join(homeDirPath, 'cache', 'cocoapods', 'repos');
|
|
fs.directory(fs.path.join(cocoapodsReposDir, 'master')).createSync(recursive: true);
|
|
return cocoapodsReposDir;
|
|
}
|
|
|
|
setUp(() async {
|
|
Cache.flutterRoot = 'flutter';
|
|
fs = MemoryFileSystem();
|
|
mockProcessManager = MockProcessManager();
|
|
mockXcodeProjectInterpreter = MockXcodeProjectInterpreter();
|
|
projectUnderTest = FlutterProject.fromDirectory(fs.directory('project'));
|
|
projectUnderTest.ios.xcodeProject.createSync(recursive: true);
|
|
cocoaPodsUnderTest = CocoaPods();
|
|
pretendPodVersionIs('1.6.0');
|
|
fs.file(fs.path.join(
|
|
Cache.flutterRoot, 'packages', 'flutter_tools', 'templates', 'cocoapods', 'Podfile-ios-objc',
|
|
))
|
|
..createSync(recursive: true)
|
|
..writeAsStringSync('Objective-C iOS podfile template');
|
|
fs.file(fs.path.join(
|
|
Cache.flutterRoot, 'packages', 'flutter_tools', 'templates', 'cocoapods', 'Podfile-ios-swift',
|
|
))
|
|
..createSync(recursive: true)
|
|
..writeAsStringSync('Swift iOS podfile template');
|
|
fs.file(fs.path.join(
|
|
Cache.flutterRoot, 'packages', 'flutter_tools', 'templates', 'cocoapods', 'Podfile-macos',
|
|
))
|
|
..createSync(recursive: true)
|
|
..writeAsStringSync('macOS podfile template');
|
|
when(mockProcessManager.run(
|
|
<String>['pod', '--version'],
|
|
workingDirectory: anyNamed('workingDirectory'),
|
|
environment: anyNamed('environment'),
|
|
)).thenAnswer((_) => resultOfPodVersion());
|
|
when(mockProcessManager.run(
|
|
<String>['pod', 'install', '--verbose'],
|
|
workingDirectory: 'project/ios',
|
|
environment: <String, String>{'FLUTTER_FRAMEWORK_DIR': 'engine/path', 'COCOAPODS_DISABLE_STATS': 'true'},
|
|
)).thenAnswer((_) async => exitsHappy());
|
|
when(mockProcessManager.run(
|
|
<String>['pod', 'install', '--verbose'],
|
|
workingDirectory: 'project/macos',
|
|
environment: <String, String>{'FLUTTER_FRAMEWORK_DIR': 'engine/path', 'COCOAPODS_DISABLE_STATS': 'true'},
|
|
)).thenAnswer((_) async => exitsHappy());
|
|
});
|
|
|
|
void pretendPodIsNotInstalled() {
|
|
when(mockProcessManager.run(
|
|
<String>['which', 'pod'],
|
|
workingDirectory: anyNamed('workingDirectory'),
|
|
environment: anyNamed('environment'),
|
|
)).thenAnswer((_) async => exitsWithError());
|
|
}
|
|
|
|
void pretendPodIsInstalled() {
|
|
when(mockProcessManager.run(
|
|
<String>['which', 'pod'],
|
|
workingDirectory: anyNamed('workingDirectory'),
|
|
environment: anyNamed('environment'),
|
|
)).thenAnswer((_) async => exitsHappy());
|
|
}
|
|
|
|
group('Evaluate installation', () {
|
|
testUsingContext('detects not installed, if pod exec does not exist', () async {
|
|
pretendPodIsNotInstalled();
|
|
expect(await cocoaPodsUnderTest.evaluateCocoaPodsInstallation, CocoaPodsStatus.notInstalled);
|
|
}, overrides: <Type, Generator>{
|
|
ProcessManager: () => mockProcessManager,
|
|
});
|
|
|
|
testUsingContext('detects not installed, if pod is installed but version fails', () async {
|
|
pretendPodIsInstalled();
|
|
pretendPodVersionFails();
|
|
expect(await cocoaPodsUnderTest.evaluateCocoaPodsInstallation, CocoaPodsStatus.brokenInstall);
|
|
}, overrides: <Type, Generator>{
|
|
ProcessManager: () => mockProcessManager,
|
|
});
|
|
|
|
testUsingContext('detects installed', () async {
|
|
pretendPodIsInstalled();
|
|
pretendPodVersionIs('0.0.1');
|
|
expect(await cocoaPodsUnderTest.evaluateCocoaPodsInstallation, isNot(CocoaPodsStatus.notInstalled));
|
|
}, overrides: <Type, Generator>{
|
|
ProcessManager: () => mockProcessManager,
|
|
});
|
|
|
|
testUsingContext('detects unknown version', () async {
|
|
pretendPodIsInstalled();
|
|
pretendPodVersionIs('Plugin loaded.\n1.5.3');
|
|
expect(await cocoaPodsUnderTest.evaluateCocoaPodsInstallation, CocoaPodsStatus.unknownVersion);
|
|
}, overrides: <Type, Generator>{
|
|
ProcessManager: () => mockProcessManager,
|
|
});
|
|
|
|
testUsingContext('detects below minimum version', () async {
|
|
pretendPodIsInstalled();
|
|
pretendPodVersionIs('1.5.0');
|
|
expect(await cocoaPodsUnderTest.evaluateCocoaPodsInstallation, CocoaPodsStatus.belowMinimumVersion);
|
|
}, overrides: <Type, Generator>{
|
|
ProcessManager: () => mockProcessManager,
|
|
});
|
|
|
|
testUsingContext('detects at recommended version', () async {
|
|
pretendPodIsInstalled();
|
|
pretendPodVersionIs('1.6.0');
|
|
expect(await cocoaPodsUnderTest.evaluateCocoaPodsInstallation, CocoaPodsStatus.recommended);
|
|
}, overrides: <Type, Generator>{
|
|
ProcessManager: () => mockProcessManager,
|
|
});
|
|
|
|
testUsingContext('detects above recommended version', () async {
|
|
pretendPodIsInstalled();
|
|
pretendPodVersionIs('1.6.1');
|
|
expect(await cocoaPodsUnderTest.evaluateCocoaPodsInstallation, CocoaPodsStatus.recommended);
|
|
}, overrides: <Type, Generator>{
|
|
ProcessManager: () => mockProcessManager,
|
|
});
|
|
|
|
testUsingContext('detects initialized over 1.8.0', () async {
|
|
pretendPodIsInstalled();
|
|
pretendPodVersionIs('1.8.0');
|
|
expect(await cocoaPodsUnderTest.isCocoaPodsInitialized, isTrue);
|
|
}, overrides: <Type, Generator>{
|
|
Platform: () => FakePlatform(),
|
|
FileSystem: () => fs,
|
|
ProcessManager: () => mockProcessManager,
|
|
});
|
|
});
|
|
|
|
group('Setup Podfile', () {
|
|
testUsingContext('creates objective-c Podfile when not present', () async {
|
|
await cocoaPodsUnderTest.setupPodfile(projectUnderTest.ios);
|
|
|
|
expect(projectUnderTest.ios.podfile.readAsStringSync(), 'Objective-C iOS podfile template');
|
|
}, overrides: <Type, Generator>{
|
|
FileSystem: () => fs,
|
|
ProcessManager: () => FakeProcessManager.any(),
|
|
});
|
|
|
|
testUsingContext('creates swift Podfile if swift', () async {
|
|
when(mockXcodeProjectInterpreter.isInstalled).thenReturn(true);
|
|
when(mockXcodeProjectInterpreter.getBuildSettings(any, any))
|
|
.thenAnswer((_) async => <String, String>{
|
|
'SWIFT_VERSION': '5.0',
|
|
});
|
|
|
|
final FlutterProject project = FlutterProject.fromPath('project');
|
|
await cocoaPodsUnderTest.setupPodfile(project.ios);
|
|
|
|
expect(projectUnderTest.ios.podfile.readAsStringSync(), 'Swift iOS podfile template');
|
|
}, overrides: <Type, Generator>{
|
|
FileSystem: () => fs,
|
|
ProcessManager: () => FakeProcessManager.any(),
|
|
XcodeProjectInterpreter: () => mockXcodeProjectInterpreter,
|
|
});
|
|
|
|
testUsingContext('creates macOS Podfile when not present', () async {
|
|
projectUnderTest.macos.xcodeProject.createSync(recursive: true);
|
|
await cocoaPodsUnderTest.setupPodfile(projectUnderTest.macos);
|
|
|
|
expect(projectUnderTest.macos.podfile.readAsStringSync(), 'macOS podfile template');
|
|
}, overrides: <Type, Generator>{
|
|
FileSystem: () => fs,
|
|
ProcessManager: () => FakeProcessManager.any(),
|
|
});
|
|
|
|
testUsingContext('does not recreate Podfile when already present', () async {
|
|
projectUnderTest.ios.podfile..createSync()..writeAsStringSync('Existing Podfile');
|
|
|
|
final FlutterProject project = FlutterProject.fromPath('project');
|
|
await cocoaPodsUnderTest.setupPodfile(project.ios);
|
|
|
|
expect(projectUnderTest.ios.podfile.readAsStringSync(), 'Existing Podfile');
|
|
}, overrides: <Type, Generator>{
|
|
FileSystem: () => fs,
|
|
ProcessManager: () => FakeProcessManager.any(),
|
|
});
|
|
|
|
testUsingContext('does not create Podfile when we cannot interpret Xcode projects', () async {
|
|
when(mockXcodeProjectInterpreter.isInstalled).thenReturn(false);
|
|
|
|
final FlutterProject project = FlutterProject.fromPath('project');
|
|
await cocoaPodsUnderTest.setupPodfile(project.ios);
|
|
|
|
expect(projectUnderTest.ios.podfile.existsSync(), false);
|
|
}, overrides: <Type, Generator>{
|
|
FileSystem: () => fs,
|
|
ProcessManager: () => FakeProcessManager.any(),
|
|
XcodeProjectInterpreter: () => mockXcodeProjectInterpreter,
|
|
});
|
|
|
|
testUsingContext('includes Pod config in xcconfig files, if not present', () async {
|
|
projectUnderTest.ios.podfile..createSync()..writeAsStringSync('Existing Podfile');
|
|
projectUnderTest.ios.xcodeConfigFor('Debug')
|
|
..createSync(recursive: true)
|
|
..writeAsStringSync('Existing debug config');
|
|
projectUnderTest.ios.xcodeConfigFor('Release')
|
|
..createSync(recursive: true)
|
|
..writeAsStringSync('Existing release config');
|
|
|
|
final FlutterProject project = FlutterProject.fromPath('project');
|
|
await cocoaPodsUnderTest.setupPodfile(project.ios);
|
|
|
|
final String debugContents = projectUnderTest.ios.xcodeConfigFor('Debug').readAsStringSync();
|
|
expect(debugContents, contains(
|
|
'#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"\n'));
|
|
expect(debugContents, contains('Existing debug config'));
|
|
final String releaseContents = projectUnderTest.ios.xcodeConfigFor('Release').readAsStringSync();
|
|
expect(releaseContents, contains(
|
|
'#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"\n'));
|
|
expect(releaseContents, contains('Existing release config'));
|
|
}, overrides: <Type, Generator>{
|
|
FileSystem: () => fs,
|
|
ProcessManager: () => FakeProcessManager.any(),
|
|
});
|
|
});
|
|
|
|
group('Update xcconfig', () {
|
|
testUsingContext('includes Pod config in xcconfig files, if the user manually added Pod dependencies without using Flutter plugins', () async {
|
|
projectUnderTest.ios.podfile..createSync()..writeAsStringSync('Custom Podfile');
|
|
projectUnderTest.ios.podfileLock..createSync()..writeAsStringSync('Podfile.lock from user executed `pod install`');
|
|
projectUnderTest.packagesFile..createSync()..writeAsStringSync('');
|
|
projectUnderTest.ios.xcodeConfigFor('Debug')
|
|
..createSync(recursive: true)
|
|
..writeAsStringSync('Existing debug config');
|
|
projectUnderTest.ios.xcodeConfigFor('Release')
|
|
..createSync(recursive: true)
|
|
..writeAsStringSync('Existing release config');
|
|
|
|
final FlutterProject project = FlutterProject.fromPath('project');
|
|
await injectPlugins(project, checkProjects: true);
|
|
|
|
final String debugContents = projectUnderTest.ios.xcodeConfigFor('Debug').readAsStringSync();
|
|
expect(debugContents, contains(
|
|
'#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"\n'));
|
|
expect(debugContents, contains('Existing debug config'));
|
|
final String releaseContents = projectUnderTest.ios.xcodeConfigFor('Release').readAsStringSync();
|
|
expect(releaseContents, contains(
|
|
'#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"\n'));
|
|
expect(releaseContents, contains('Existing release config'));
|
|
}, overrides: <Type, Generator>{
|
|
FileSystem: () => fs,
|
|
ProcessManager: () => FakeProcessManager.any(),
|
|
});
|
|
});
|
|
|
|
group('Process pods', () {
|
|
setUp(() {
|
|
podsIsInHomeDir();
|
|
});
|
|
|
|
testUsingContext('prints error, if CocoaPods is not installed', () async {
|
|
pretendPodIsNotInstalled();
|
|
projectUnderTest.ios.podfile.createSync();
|
|
final bool didInstall = await cocoaPodsUnderTest.processPods(
|
|
xcodeProject: projectUnderTest.ios,
|
|
engineDir: 'engine/path',
|
|
);
|
|
verifyNever(mockProcessManager.run(
|
|
argThat(containsAllInOrder(<String>['pod', 'install'])),
|
|
workingDirectory: anyNamed('workingDirectory'),
|
|
environment: anyNamed('environment'),
|
|
));
|
|
expect(testLogger.errorText, contains('not installed'));
|
|
expect(testLogger.errorText, contains('Skipping pod install'));
|
|
expect(didInstall, isFalse);
|
|
}, overrides: <Type, Generator>{
|
|
FileSystem: () => fs,
|
|
ProcessManager: () => mockProcessManager,
|
|
});
|
|
|
|
testUsingContext('prints warning, if Podfile is out of date', () async {
|
|
pretendPodIsInstalled();
|
|
|
|
fs.file(fs.path.join('project', 'ios', 'Podfile'))
|
|
..createSync()
|
|
..writeAsStringSync('Existing Podfile');
|
|
|
|
final Directory symlinks = projectUnderTest.ios.symlinks
|
|
..createSync(recursive: true);
|
|
symlinks.childLink('flutter').createSync('cache');
|
|
|
|
await cocoaPodsUnderTest.processPods(
|
|
xcodeProject: projectUnderTest.ios,
|
|
engineDir: 'engine/path',
|
|
);
|
|
expect(testLogger.errorText, contains('Warning: Podfile is out of date'));
|
|
}, overrides: <Type, Generator>{
|
|
FileSystem: () => fs,
|
|
ProcessManager: () => mockProcessManager,
|
|
});
|
|
|
|
testUsingContext('throws, if Podfile is missing.', () async {
|
|
pretendPodIsInstalled();
|
|
try {
|
|
await cocoaPodsUnderTest.processPods(
|
|
xcodeProject: projectUnderTest.ios,
|
|
engineDir: 'engine/path',
|
|
);
|
|
fail('ToolExit expected');
|
|
} catch(e) {
|
|
expect(e, isInstanceOf<ToolExit>());
|
|
verifyNever(mockProcessManager.run(
|
|
argThat(containsAllInOrder(<String>['pod', 'install'])),
|
|
workingDirectory: anyNamed('workingDirectory'),
|
|
environment: anyNamed('environment'),
|
|
));
|
|
}
|
|
}, overrides: <Type, Generator>{
|
|
FileSystem: () => fs,
|
|
ProcessManager: () => mockProcessManager,
|
|
});
|
|
|
|
testUsingContext('throws, if specs repo is outdated.', () async {
|
|
pretendPodIsInstalled();
|
|
fs.file(fs.path.join('project', 'ios', 'Podfile'))
|
|
..createSync()
|
|
..writeAsStringSync('Existing Podfile');
|
|
|
|
when(mockProcessManager.run(
|
|
<String>['pod', 'install', '--verbose'],
|
|
workingDirectory: 'project/ios',
|
|
environment: <String, String>{
|
|
'FLUTTER_FRAMEWORK_DIR': 'engine/path',
|
|
'COCOAPODS_DISABLE_STATS': 'true',
|
|
},
|
|
)).thenAnswer((_) async => exitsWithError(
|
|
'''
|
|
[!] 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(
|
|
xcodeProject: projectUnderTest.ios,
|
|
engineDir: 'engine/path',
|
|
);
|
|
fail('ToolExit expected');
|
|
} catch (e) {
|
|
expect(e, isInstanceOf<ToolExit>());
|
|
expect(
|
|
testLogger.errorText,
|
|
contains("CocoaPods's specs repository is too out-of-date to satisfy dependencies"),
|
|
);
|
|
}
|
|
}, overrides: <Type, Generator>{
|
|
FileSystem: () => fs,
|
|
ProcessManager: () => mockProcessManager,
|
|
});
|
|
|
|
testUsingContext('run pod install, if Podfile.lock is missing', () async {
|
|
pretendPodIsInstalled();
|
|
projectUnderTest.ios.podfile
|
|
..createSync()
|
|
..writeAsStringSync('Existing Podfile');
|
|
projectUnderTest.ios.podManifestLock
|
|
..createSync(recursive: true)
|
|
..writeAsStringSync('Existing lock file.');
|
|
final bool didInstall = await cocoaPodsUnderTest.processPods(
|
|
xcodeProject: projectUnderTest.ios,
|
|
engineDir: 'engine/path',
|
|
dependenciesChanged: false,
|
|
);
|
|
expect(didInstall, isTrue);
|
|
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>{
|
|
FileSystem: () => fs,
|
|
ProcessManager: () => mockProcessManager,
|
|
});
|
|
|
|
testUsingContext('runs pod install, if Manifest.lock is missing', () async {
|
|
pretendPodIsInstalled();
|
|
projectUnderTest.ios.podfile
|
|
..createSync()
|
|
..writeAsStringSync('Existing Podfile');
|
|
projectUnderTest.ios.podfileLock
|
|
..createSync()
|
|
..writeAsStringSync('Existing lock file.');
|
|
final bool didInstall = await cocoaPodsUnderTest.processPods(
|
|
xcodeProject: projectUnderTest.ios,
|
|
engineDir: 'engine/path',
|
|
dependenciesChanged: false,
|
|
);
|
|
expect(didInstall, isTrue);
|
|
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>{
|
|
FileSystem: () => fs,
|
|
ProcessManager: () => mockProcessManager,
|
|
});
|
|
|
|
testUsingContext('runs pod install, if Manifest.lock different from Podspec.lock', () async {
|
|
pretendPodIsInstalled();
|
|
projectUnderTest.ios.podfile
|
|
..createSync()
|
|
..writeAsStringSync('Existing Podfile');
|
|
projectUnderTest.ios.podfileLock
|
|
..createSync()
|
|
..writeAsStringSync('Existing lock file.');
|
|
projectUnderTest.ios.podManifestLock
|
|
..createSync(recursive: true)
|
|
..writeAsStringSync('Different lock file.');
|
|
final bool didInstall = await cocoaPodsUnderTest.processPods(
|
|
xcodeProject: projectUnderTest.ios,
|
|
engineDir: 'engine/path',
|
|
dependenciesChanged: false,
|
|
);
|
|
expect(didInstall, isTrue);
|
|
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>{
|
|
FileSystem: () => fs,
|
|
ProcessManager: () => mockProcessManager,
|
|
});
|
|
|
|
testUsingContext('runs pod install, if flutter framework changed', () async {
|
|
pretendPodIsInstalled();
|
|
projectUnderTest.ios.podfile
|
|
..createSync()
|
|
..writeAsStringSync('Existing Podfile');
|
|
projectUnderTest.ios.podfileLock
|
|
..createSync()
|
|
..writeAsStringSync('Existing lock file.');
|
|
projectUnderTest.ios.podManifestLock
|
|
..createSync(recursive: true)
|
|
..writeAsStringSync('Existing lock file.');
|
|
final bool didInstall = await cocoaPodsUnderTest.processPods(
|
|
xcodeProject: projectUnderTest.ios,
|
|
engineDir: 'engine/path',
|
|
dependenciesChanged: true,
|
|
);
|
|
expect(didInstall, isTrue);
|
|
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>{
|
|
FileSystem: () => fs,
|
|
ProcessManager: () => mockProcessManager,
|
|
});
|
|
|
|
testUsingContext('runs pod install, if Podfile.lock is older than Podfile', () async {
|
|
pretendPodIsInstalled();
|
|
projectUnderTest.ios.podfile
|
|
..createSync()
|
|
..writeAsStringSync('Existing Podfile');
|
|
projectUnderTest.ios.podfileLock
|
|
..createSync()
|
|
..writeAsStringSync('Existing lock file.');
|
|
projectUnderTest.ios.podManifestLock
|
|
..createSync(recursive: true)
|
|
..writeAsStringSync('Existing lock file.');
|
|
await Future<void>.delayed(const Duration(milliseconds: 10));
|
|
projectUnderTest.ios.podfile
|
|
..writeAsStringSync('Updated Podfile');
|
|
await cocoaPodsUnderTest.processPods(
|
|
xcodeProject: projectUnderTest.ios,
|
|
engineDir: 'engine/path',
|
|
dependenciesChanged: false,
|
|
);
|
|
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>{
|
|
FileSystem: () => fs,
|
|
ProcessManager: () => mockProcessManager,
|
|
});
|
|
|
|
testUsingContext('skips pod install, if nothing changed', () async {
|
|
pretendPodIsInstalled();
|
|
projectUnderTest.ios.podfile
|
|
..createSync()
|
|
..writeAsStringSync('Existing Podfile');
|
|
projectUnderTest.ios.podfileLock
|
|
..createSync()
|
|
..writeAsStringSync('Existing lock file.');
|
|
projectUnderTest.ios.podManifestLock
|
|
..createSync(recursive: true)
|
|
..writeAsStringSync('Existing lock file.');
|
|
final bool didInstall = await cocoaPodsUnderTest.processPods(
|
|
xcodeProject: projectUnderTest.ios,
|
|
engineDir: 'engine/path',
|
|
dependenciesChanged: false,
|
|
);
|
|
expect(didInstall, isFalse);
|
|
verifyNever(mockProcessManager.run(
|
|
argThat(containsAllInOrder(<String>['pod', 'install'])),
|
|
workingDirectory: anyNamed('workingDirectory'),
|
|
environment: anyNamed('environment'),
|
|
));
|
|
}, overrides: <Type, Generator>{
|
|
FileSystem: () => fs,
|
|
ProcessManager: () => mockProcessManager,
|
|
});
|
|
|
|
testUsingContext('a failed pod install deletes Pods/Manifest.lock', () async {
|
|
pretendPodIsInstalled();
|
|
projectUnderTest.ios.podfile
|
|
..createSync()
|
|
..writeAsStringSync('Existing Podfile');
|
|
projectUnderTest.ios.podfileLock
|
|
..createSync()
|
|
..writeAsStringSync('Existing lock file.');
|
|
projectUnderTest.ios.podManifestLock
|
|
..createSync(recursive: true)
|
|
..writeAsStringSync('Existing lock file.');
|
|
|
|
when(mockProcessManager.run(
|
|
<String>['pod', 'install', '--verbose'],
|
|
workingDirectory: 'project/ios',
|
|
environment: <String, String>{
|
|
'FLUTTER_FRAMEWORK_DIR': 'engine/path',
|
|
'COCOAPODS_DISABLE_STATS': 'true',
|
|
},
|
|
)).thenAnswer(
|
|
(_) async => exitsWithError()
|
|
);
|
|
|
|
try {
|
|
await cocoaPodsUnderTest.processPods(
|
|
xcodeProject: projectUnderTest.ios,
|
|
engineDir: 'engine/path',
|
|
dependenciesChanged: true,
|
|
);
|
|
fail('Tool throw expected when pod install fails');
|
|
} on ToolExit {
|
|
expect(projectUnderTest.ios.podManifestLock.existsSync(), isFalse);
|
|
}
|
|
}, overrides: <Type, Generator>{
|
|
FileSystem: () => fs,
|
|
ProcessManager: () => mockProcessManager,
|
|
});
|
|
});
|
|
|
|
group('Pods repos dir is custom', () {
|
|
String cocoapodsRepoDir;
|
|
Map<String, String> environment;
|
|
setUp(() {
|
|
cocoapodsRepoDir = podsIsInCustomDir();
|
|
environment = <String, String>{
|
|
'FLUTTER_FRAMEWORK_DIR': 'engine/path',
|
|
'COCOAPODS_DISABLE_STATS': 'true',
|
|
'CP_REPOS_DIR': cocoapodsRepoDir,
|
|
};
|
|
});
|
|
|
|
testUsingContext('succeeds, if specs repo is in CP_REPOS_DIR.', () async {
|
|
pretendPodIsInstalled();
|
|
fs.file(fs.path.join('project', 'ios', 'Podfile'))
|
|
..createSync()
|
|
..writeAsStringSync('Existing Podfile');
|
|
|
|
when(mockProcessManager.run(
|
|
<String>['pod', 'install', '--verbose'],
|
|
workingDirectory: 'project/ios',
|
|
environment: environment,
|
|
)).thenAnswer((_) async => exitsHappy());
|
|
final bool success = await cocoaPodsUnderTest.processPods(
|
|
xcodeProject: projectUnderTest.ios,
|
|
engineDir: 'engine/path',
|
|
);
|
|
expect(success, true);
|
|
}, overrides: <Type, Generator>{
|
|
FileSystem: () => fs,
|
|
ProcessManager: () => mockProcessManager,
|
|
Platform: () => FakePlatform(environment: environment),
|
|
});
|
|
});
|
|
}
|
|
|
|
class MockProcessManager extends Mock implements ProcessManager {}
|
|
class MockXcodeProjectInterpreter extends Mock implements XcodeProjectInterpreter {}
|
|
|
|
ProcessResult exitsWithError([ String stdout = '' ]) => ProcessResult(1, 1, stdout, '');
|
|
ProcessResult exitsHappy([ String stdout = '' ]) => ProcessResult(1, 0, stdout, '');
|