Unverified Commit 8a33d244 authored by Zachary Anderson's avatar Zachary Anderson Committed by GitHub

[flutter_tool] Remove the synchronous -showBuildSettings (#40435)

parent ef126954
......@@ -328,7 +328,7 @@ abstract class IOSApp extends ApplicationPackage {
);
}
factory IOSApp.fromIosProject(IosProject project) {
static Future<IOSApp> fromIosProject(IosProject project) {
if (getCurrentHostPlatform() != HostPlatform.darwin_x64) {
return null;
}
......@@ -345,7 +345,7 @@ abstract class IOSApp extends ApplicationPackage {
printError('Expected ios/Runner.xcodeproj/project.pbxproj but this file is missing.');
return null;
}
return BuildableIOSApp(project);
return BuildableIOSApp.fromProject(project);
}
@override
......@@ -357,7 +357,13 @@ abstract class IOSApp extends ApplicationPackage {
}
class BuildableIOSApp extends IOSApp {
BuildableIOSApp(this.project) : super(projectBundleId: project.productBundleIdentifier);
BuildableIOSApp(this.project, String projectBundleId)
: super(projectBundleId: projectBundleId);
static Future<BuildableIOSApp> fromProject(IosProject project) async {
final String projectBundleId = await project.productBundleIdentifier;
return BuildableIOSApp(project, projectBundleId);
}
final IosProject project;
......@@ -416,7 +422,7 @@ class ApplicationPackageStore {
android ??= await AndroidApk.fromAndroidProject(FlutterProject.current().android);
return android;
case TargetPlatform.ios:
iOS ??= IOSApp.fromIosProject(FlutterProject.current().ios);
iOS ??= await IOSApp.fromIosProject(FlutterProject.current().ios);
return iOS;
case TargetPlatform.fuchsia:
fuchsia ??= FuchsiaApp.fromFuchsiaProject(FlutterProject.current().fuchsia);
......
......@@ -352,7 +352,7 @@ class CreateCommand extends FlutterCommand {
String organization = argResults['org'];
if (!argResults.wasParsed('org')) {
final FlutterProject project = FlutterProject.fromDirectory(projectDir);
final Set<String> existingOrganizations = project.organizationNames;
final Set<String> existingOrganizations = await project.organizationNames;
if (existingOrganizations.length == 1) {
organization = existingOrganizations.first;
} else if (1 < existingOrganizations.length) {
......
......@@ -231,7 +231,7 @@ class RunCommand extends RunCommandBase {
hostLanguage.add(androidProject.isKotlin ? 'kotlin' : 'java');
}
if (iosProject != null && iosProject.exists) {
hostLanguage.add(iosProject.isSwift ? 'swift' : 'objc');
hostLanguage.add(await iosProject.isSwift ? 'swift' : 'objc');
}
return <CustomDimensions, String>{
......
......@@ -95,7 +95,7 @@ final RegExp _certificateOrganizationalUnitExtractionPattern = RegExp(r'OU=([a-z
Future<Map<String, String>> getCodeSigningIdentityDevelopmentTeam({
BuildableIOSApp iosApp,
}) async {
final Map<String, String> buildSettings = iosApp.project.buildSettings;
final Map<String, String> buildSettings = await iosApp.project.buildSettings;
if (buildSettings == null) {
return null;
}
......
......@@ -258,32 +258,9 @@ class XcodeProjectInterpreter {
return _minorVersion;
}
/// Synchronously retrieve xcode build settings. Prefer using the async
/// version below.
Map<String, String> getBuildSettings(String projectPath, String target) {
try {
final String out = processUtils.runSync(
<String>[
_executable,
'-project',
fs.path.absolute(projectPath),
'-target',
target,
'-showBuildSettings',
],
throwOnError: true,
workingDirectory: projectPath,
).stdout.trim();
return parseXcodeBuildSettings(out);
} on ProcessException catch (error) {
printTrace('Unexpected failure to get the build settings: $error.');
return const <String, String>{};
}
}
/// Asynchronously retrieve xcode build settings. This one is preferred for
/// new call-sites.
Future<Map<String, String>> getBuildSettingsAsync(
Future<Map<String, String>> getBuildSettings(
String projectPath, String target, {
Duration timeout = const Duration(minutes: 1),
}) async {
......
......@@ -37,7 +37,7 @@ Future<void> processPodsIfNeeded(XcodeBasedProject xcodeProject,
final bool didPodInstall = await cocoaPods.processPods(
xcodeProject: xcodeProject,
engineDir: flutterFrameworkDir(buildMode),
isSwift: xcodeProject.isSwift,
isSwift: await xcodeProject.isSwift,
dependenciesChanged: !fingerprinter.doesFingerprintMatch(),
);
if (didPodInstall) {
......
......@@ -213,7 +213,7 @@ class CocoaPods {
if (xcodeProject is MacOSProject) {
podfileTemplateName = 'Podfile-macos';
} else {
final bool isSwift = (await xcodeProjectInterpreter.getBuildSettingsAsync(
final bool isSwift = (await xcodeProjectInterpreter.getBuildSettings(
runnerProject.path,
'Runner',
)).containsKey('SWIFT_VERSION');
......
......@@ -88,13 +88,13 @@ class FlutterProject {
/// The set of organization names found in this project as
/// part of iOS product bundle identifier, Android application ID, or
/// Gradle group ID.
Set<String> get organizationNames {
Future<Set<String>> get organizationNames async {
final List<String> candidates = <String>[
ios.productBundleIdentifier,
await ios.productBundleIdentifier,
android.applicationId,
android.group,
example.android.applicationId,
example.ios.productBundleIdentifier,
await example.ios.productBundleIdentifier,
];
return Set<String>.from(candidates
.map<String>(_organizationNameFromPackageName)
......@@ -280,7 +280,7 @@ abstract class XcodeBasedProject {
File get podManifestLock;
/// True if the host app project is using Swift.
bool get isSwift;
Future<bool> get isSwift;
}
/// Represents the iOS sub-project of a Flutter project.
......@@ -365,7 +365,7 @@ class IosProject implements XcodeBasedProject {
/// The product bundle identifier of the host app, or null if not set or if
/// iOS tooling needed to read it is not installed.
String get productBundleIdentifier {
Future<String> get productBundleIdentifier async {
String fromPlist;
try {
fromPlist = PlistParser.instance.getValueFromFile(
......@@ -386,24 +386,26 @@ class IosProject implements XcodeBasedProject {
}
if (fromPlist != null && xcode.xcodeProjectInterpreter.isInstalled) {
// General case: perform variable substitution using build settings.
return xcode.substituteXcodeVariables(fromPlist, buildSettings);
return xcode.substituteXcodeVariables(fromPlist, await buildSettings);
}
return null;
}
@override
bool get isSwift => buildSettings?.containsKey('SWIFT_VERSION') ?? false;
Future<bool> get isSwift async =>
(await buildSettings)?.containsKey('SWIFT_VERSION') ?? false;
/// The build settings for the host app of this project, as a detached map.
///
/// Returns null, if iOS tooling is unavailable.
Map<String, String> get buildSettings {
Future<Map<String, String>> get buildSettings async {
if (!xcode.xcodeProjectInterpreter.isInstalled) {
return null;
}
_buildSettings ??=
xcode.xcodeProjectInterpreter.getBuildSettings(xcodeProject.path,
_hostAppBundleName);
_buildSettings ??= await xcode.xcodeProjectInterpreter.getBuildSettings(
xcodeProject.path,
_hostAppBundleName,
);
return _buildSettings;
}
......@@ -726,7 +728,7 @@ class MacOSProject implements XcodeBasedProject {
Directory get xcodeWorkspace => _macOSDirectory.childDirectory('$_hostAppBundleName.xcworkspace');
@override
bool get isSwift => true;
Future<bool> get isSwift async => true;
/// The file where the Xcode build will write the name of the built app.
///
......
......@@ -325,7 +325,8 @@ void main() {
testUsingContext('returns null when there is no ios or .ios directory', () async {
fs.file('pubspec.yaml').createSync();
fs.file('.packages').createSync();
final BuildableIOSApp iosApp = IOSApp.fromIosProject(FlutterProject.fromDirectory(fs.currentDirectory).ios);
final BuildableIOSApp iosApp = await IOSApp.fromIosProject(
FlutterProject.fromDirectory(fs.currentDirectory).ios);
expect(iosApp, null);
}, overrides: overrides);
......@@ -334,7 +335,8 @@ void main() {
fs.file('pubspec.yaml').createSync();
fs.file('.packages').createSync();
fs.file('ios/FooBar.xcodeproj').createSync(recursive: true);
final BuildableIOSApp iosApp = IOSApp.fromIosProject(FlutterProject.fromDirectory(fs.currentDirectory).ios);
final BuildableIOSApp iosApp = await IOSApp.fromIosProject(
FlutterProject.fromDirectory(fs.currentDirectory).ios);
expect(iosApp, null);
}, overrides: overrides);
......@@ -343,7 +345,8 @@ void main() {
fs.file('pubspec.yaml').createSync();
fs.file('.packages').createSync();
fs.file('ios/Runner.xcodeproj').createSync(recursive: true);
final BuildableIOSApp iosApp = IOSApp.fromIosProject(FlutterProject.fromDirectory(fs.currentDirectory).ios);
final BuildableIOSApp iosApp = await IOSApp.fromIosProject(
FlutterProject.fromDirectory(fs.currentDirectory).ios);
expect(iosApp, null);
}, overrides: overrides);
......
......@@ -707,7 +707,7 @@ void main() {
await runner.run(<String>['create', '--template=app', '--no-pub', '--org', 'com.example', tmpProjectDir]);
FlutterProject project = FlutterProject.fromDirectory(fs.directory(tmpProjectDir));
expect(
project.ios.productBundleIdentifier,
await project.ios.productBundleIdentifier,
'com.example.helloFlutter',
);
expect(
......@@ -719,7 +719,7 @@ void main() {
await runner.run(<String>['create', '--template=app', '--no-pub', '--org', 'abc^*.1#@', tmpProjectDir]);
project = FlutterProject.fromDirectory(fs.directory(tmpProjectDir));
expect(
project.ios.productBundleIdentifier,
await project.ios.productBundleIdentifier,
'abc.1.testAbc',
);
expect(
......@@ -731,7 +731,7 @@ void main() {
await runner.run(<String>['create', '--template=app', '--no-pub', '--org', '#+^%', tmpProjectDir]);
project = FlutterProject.fromDirectory(fs.directory(tmpProjectDir));
expect(
project.ios.productBundleIdentifier,
await project.ios.productBundleIdentifier,
'flutterProject.untitled',
);
expect(
......@@ -856,7 +856,7 @@ void main() {
await _createProject(projectDir, <String>[], <String>[]);
final FlutterProject project = FlutterProject.fromDirectory(projectDir);
expect(
project.ios.productBundleIdentifier,
await project.ios.productBundleIdentifier,
'com.bar.foo.flutterProject',
);
}, timeout: allowForRemotePubInvocation);
......@@ -896,7 +896,7 @@ void main() {
await _createProject(projectDir, <String>['--no-pub'], <String>[]);
final FlutterProject project = FlutterProject.fromDirectory(projectDir);
expect(
project.ios.productBundleIdentifier,
await project.ios.productBundleIdentifier,
'com.bar.foo.flutterProject',
);
}, timeout: allowForCreateFlutterProject);
......@@ -929,7 +929,7 @@ void main() {
);
final FlutterProject project = FlutterProject.fromDirectory(projectDir);
expect(
project.example.ios.productBundleIdentifier,
await project.example.ios.productBundleIdentifier,
'com.bar.foo.flutterProjectExample',
);
}, timeout: allowForCreateFlutterProject);
......
......@@ -27,16 +27,18 @@ void main() {
BuildableIOSApp app;
AnsiTerminal testTerminal;
setUp(() {
setUp(() async {
mockProcessManager = MockProcessManager();
mockConfig = MockConfig();
mockIosProject = MockIosProject();
when(mockIosProject.buildSettings).thenReturn(<String, String>{
'For our purposes': 'a non-empty build settings map is valid',
when(mockIosProject.buildSettings).thenAnswer((_) {
return Future<Map<String, String>>.value(<String, String>{
'For our purposes': 'a non-empty build settings map is valid',
});
});
testTerminal = TestTerminal();
testTerminal.usesTerminalUi = true;
app = BuildableIOSApp(mockIosProject);
app = await BuildableIOSApp.fromProject(mockIosProject);
});
testUsingContext('No auto-sign if Xcode project settings are not available', () async {
......@@ -46,8 +48,10 @@ void main() {
});
testUsingContext('No discovery if development team specified in Xcode project', () async {
when(mockIosProject.buildSettings).thenReturn(<String, String>{
'DEVELOPMENT_TEAM': 'abc',
when(mockIosProject.buildSettings).thenAnswer((_) {
return Future<Map<String, String>>.value(<String, String>{
'DEVELOPMENT_TEAM': 'abc',
});
});
final Map<String, String> signingConfigs = await getCodeSigningIdentityDevelopmentTeam(iosApp: app);
expect(signingConfigs, isNull);
......
......@@ -295,8 +295,8 @@ void main() {
projectDir.path,
]);
final IOSApp app =
AbsoluteBuildableIOSApp(FlutterProject.fromDirectory(projectDir).ios);
final IOSApp app = await AbsoluteBuildableIOSApp.fromProject(
FlutterProject.fromDirectory(projectDir).ios);
final IOSDevice device = IOSDevice('123');
// Pre-create the expected build products.
......@@ -547,7 +547,7 @@ Runner(UIKit)[297] <Notice>: E is for enpitsu"
final IOSDevice device = IOSDevice('123456');
final DeviceLogReader logReader = device.getLogReader(
app: BuildableIOSApp(mockIosProject),
app: await BuildableIOSApp.fromProject(mockIosProject),
);
final List<String> lines = await logReader.logLines.toList();
......@@ -572,7 +572,7 @@ Runner(libsystem_asl.dylib)[297] <Notice>: libMobileGestalt
final IOSDevice device = IOSDevice('123456');
final DeviceLogReader logReader = device.getLogReader(
app: BuildableIOSApp(mockIosProject),
app: await BuildableIOSApp.fromProject(mockIosProject),
);
final List<String> lines = await logReader.logLines.toList();
......@@ -630,7 +630,13 @@ flutter:
}
class AbsoluteBuildableIOSApp extends BuildableIOSApp {
AbsoluteBuildableIOSApp(IosProject project) : super(project);
AbsoluteBuildableIOSApp(IosProject project, String projectBundleId) :
super(project, projectBundleId);
static Future<AbsoluteBuildableIOSApp> fromProject(IosProject project) async {
final String projectBundleId = await project.productBundleIdentifier;
return AbsoluteBuildableIOSApp(project, projectBundleId);
}
@override
String get deviceBundlePath =>
......
......@@ -338,7 +338,7 @@ void main() {
final IOSSimulator device = IOSSimulator('123456', simulatorCategory: 'iOS 11.0');
final DeviceLogReader logReader = device.getLogReader(
app: BuildableIOSApp(mockIosProject),
app: await BuildableIOSApp.fromProject(mockIosProject),
);
final List<String> lines = await logReader.logLines.toList();
......
......@@ -145,13 +145,13 @@ void main() {
expect(xcodeProjectInterpreter.isInstalled, isTrue);
});
testUsingOsxContext('build settings is empty when xcodebuild failed to get the build settings', () {
testUsingOsxContext('build settings is empty when xcodebuild failed to get the build settings', () async {
when(mockProcessManager.runSync(
argThat(contains(xcodebuild)),
workingDirectory: anyNamed('workingDirectory'),
environment: anyNamed('environment')))
.thenReturn(ProcessResult(0, 1, '', ''));
expect(xcodeProjectInterpreter.getBuildSettings('', ''), const <String, String>{});
expect(await xcodeProjectInterpreter.getBuildSettings('', ''), const <String, String>{});
});
testUsingContext('build settings flakes', () async {
......@@ -160,7 +160,7 @@ void main() {
flakes: 1,
delay: delay + const Duration(seconds: 1),
);
expect(await xcodeProjectInterpreter.getBuildSettingsAsync(
expect(await xcodeProjectInterpreter.getBuildSettings(
'', '', timeout: delay),
const <String, String>{});
// build settings times out and is killed once, then succeeds.
......
......@@ -173,7 +173,7 @@ void main() {
testUsingContext('creates swift Podfile if swift', () async {
when(mockXcodeProjectInterpreter.isInstalled).thenReturn(true);
when(mockXcodeProjectInterpreter.getBuildSettingsAsync(any, any))
when(mockXcodeProjectInterpreter.getBuildSettings(any, any))
.thenAnswer((_) async => <String, String>{
'SWIFT_VERSION': '4.0',
});
......
......@@ -257,15 +257,18 @@ void main() {
testInMemory('default host app language', () async {
final FlutterProject project = await someProject();
expect(project.ios.isSwift, isFalse);
expect(await project.ios.isSwift, isFalse);
expect(project.android.isKotlin, isFalse);
});
testUsingContext('swift and kotlin host app language', () async {
final FlutterProject project = await someProject();
when(mockXcodeProjectInterpreter.getBuildSettings(any, any)).thenReturn(<String, String>{
'SWIFT_VERSION': '4.0',
when(mockXcodeProjectInterpreter.getBuildSettings(any, any)).thenAnswer(
(_) {
return Future<Map<String, String>>.value(<String, String>{
'SWIFT_VERSION': '4.0',
});
});
addAndroidGradleFile(project.directory,
gradleFileContent: () {
......@@ -274,7 +277,7 @@ apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
''';
});
expect(project.ios.isSwift, isTrue);
expect(await project.ios.isSwift, isTrue);
expect(project.android.isKotlin, isTrue);
}, overrides: <Type, Generator>{
FileSystem: () => fs,
......@@ -306,19 +309,19 @@ apply plugin: 'kotlin-android'
testWithMocks('null, if no pbxproj or plist entries', () async {
final FlutterProject project = await someProject();
expect(project.ios.productBundleIdentifier, isNull);
expect(await project.ios.productBundleIdentifier, isNull);
});
testWithMocks('from pbxproj file, if no plist', () async {
final FlutterProject project = await someProject();
addIosProjectFile(project.directory, projectFileContent: () {
return projectFileWithBundleId('io.flutter.someProject');
});
expect(project.ios.productBundleIdentifier, 'io.flutter.someProject');
expect(await project.ios.productBundleIdentifier, 'io.flutter.someProject');
});
testWithMocks('from plist, if no variables', () async {
final FlutterProject project = await someProject();
when(mockPlistUtils.getValueFromFile(any, any)).thenReturn('io.flutter.someProject');
expect(project.ios.productBundleIdentifier, 'io.flutter.someProject');
expect(await project.ios.productBundleIdentifier, 'io.flutter.someProject');
});
testWithMocks('from pbxproj and plist, if default variable', () async {
final FlutterProject project = await someProject();
......@@ -326,56 +329,60 @@ apply plugin: 'kotlin-android'
return projectFileWithBundleId('io.flutter.someProject');
});
when(mockPlistUtils.getValueFromFile(any, any)).thenReturn('\$(PRODUCT_BUNDLE_IDENTIFIER)');
expect(project.ios.productBundleIdentifier, 'io.flutter.someProject');
expect(await project.ios.productBundleIdentifier, 'io.flutter.someProject');
});
testWithMocks('from pbxproj and plist, by substitution', () async {
final FlutterProject project = await someProject();
when(mockXcodeProjectInterpreter.getBuildSettings(any, any)).thenReturn(<String, String>{
'PRODUCT_BUNDLE_IDENTIFIER': 'io.flutter.someProject',
'SUFFIX': 'suffix',
});
when(mockXcodeProjectInterpreter.getBuildSettings(any, any)).thenAnswer(
(_) {
return Future<Map<String,String>>.value(<String, String>{
'PRODUCT_BUNDLE_IDENTIFIER': 'io.flutter.someProject',
'SUFFIX': 'suffix',
});
}
);
when(mockPlistUtils.getValueFromFile(any, any)).thenReturn('\$(PRODUCT_BUNDLE_IDENTIFIER).\$(SUFFIX)');
expect(project.ios.productBundleIdentifier, 'io.flutter.someProject.suffix');
expect(await project.ios.productBundleIdentifier, 'io.flutter.someProject.suffix');
});
testWithMocks('empty surrounded by quotes', () async {
final FlutterProject project = await someProject();
addIosProjectFile(project.directory, projectFileContent: () {
return projectFileWithBundleId('', qualifier: '"');
});
expect(project.ios.productBundleIdentifier, '');
expect(await project.ios.productBundleIdentifier, '');
});
testWithMocks('surrounded by double quotes', () async {
final FlutterProject project = await someProject();
addIosProjectFile(project.directory, projectFileContent: () {
return projectFileWithBundleId('io.flutter.someProject', qualifier: '"');
});
expect(project.ios.productBundleIdentifier, 'io.flutter.someProject');
expect(await project.ios.productBundleIdentifier, 'io.flutter.someProject');
});
testWithMocks('surrounded by single quotes', () async {
final FlutterProject project = await someProject();
addIosProjectFile(project.directory, projectFileContent: () {
return projectFileWithBundleId('io.flutter.someProject', qualifier: '\'');
});
expect(project.ios.productBundleIdentifier, 'io.flutter.someProject');
expect(await project.ios.productBundleIdentifier, 'io.flutter.someProject');
});
});
group('organization names set', () {
testInMemory('is empty, if project not created', () async {
final FlutterProject project = await someProject();
expect(project.organizationNames, isEmpty);
expect(await project.organizationNames, isEmpty);
});
testInMemory('is empty, if no platform folders exist', () async {
final FlutterProject project = await someProject();
project.directory.createSync();
expect(project.organizationNames, isEmpty);
expect(await project.organizationNames, isEmpty);
});
testInMemory('is populated from iOS bundle identifier', () async {
final FlutterProject project = await someProject();
addIosProjectFile(project.directory, projectFileContent: () {
return projectFileWithBundleId('io.flutter.someProject', qualifier: '\'');
});
expect(project.organizationNames, <String>['io.flutter']);
expect(await project.organizationNames, <String>['io.flutter']);
});
testInMemory('is populated from Android application ID', () async {
final FlutterProject project = await someProject();
......@@ -383,14 +390,14 @@ apply plugin: 'kotlin-android'
gradleFileContent: () {
return gradleFileWithApplicationId('io.flutter.someproject');
});
expect(project.organizationNames, <String>['io.flutter']);
expect(await project.organizationNames, <String>['io.flutter']);
});
testInMemory('is populated from iOS bundle identifier in plugin example', () async {
final FlutterProject project = await someProject();
addIosProjectFile(project.example.directory, projectFileContent: () {
return projectFileWithBundleId('io.flutter.someProject', qualifier: '\'');
});
expect(project.organizationNames, <String>['io.flutter']);
expect(await project.organizationNames, <String>['io.flutter']);
});
testInMemory('is populated from Android application ID in plugin example', () async {
final FlutterProject project = await someProject();
......@@ -398,12 +405,12 @@ apply plugin: 'kotlin-android'
gradleFileContent: () {
return gradleFileWithApplicationId('io.flutter.someproject');
});
expect(project.organizationNames, <String>['io.flutter']);
expect(await project.organizationNames, <String>['io.flutter']);
});
testInMemory('is populated from Android group in plugin', () async {
final FlutterProject project = await someProject();
addAndroidWithGroup(project.directory, 'io.flutter.someproject');
expect(project.organizationNames, <String>['io.flutter']);
expect(await project.organizationNames, <String>['io.flutter']);
});
testInMemory('is singleton, if sources agree', () async {
final FlutterProject project = await someProject();
......@@ -414,7 +421,7 @@ apply plugin: 'kotlin-android'
gradleFileContent: () {
return gradleFileWithApplicationId('io.flutter.someproject');
});
expect(project.organizationNames, <String>['io.flutter']);
expect(await project.organizationNames, <String>['io.flutter']);
});
testInMemory('is non-singleton, if sources disagree', () async {
final FlutterProject project = await someProject();
......@@ -426,7 +433,7 @@ apply plugin: 'kotlin-android'
return gradleFileWithApplicationId('io.clutter.someproject');
});
expect(
project.organizationNames,
await project.organizationNames,
<String>['io.flutter', 'io.clutter'],
);
});
......
......@@ -333,12 +333,7 @@ class FakeXcodeProjectInterpreter implements XcodeProjectInterpreter {
int get minorVersion => 2;
@override
Map<String, String> getBuildSettings(String projectPath, String target) {
return <String, String>{};
}
@override
Future<Map<String, String>> getBuildSettingsAsync(
Future<Map<String, String>> getBuildSettings(
String projectPath,
String target, {
Duration timeout = const Duration(minutes: 1),
......
......@@ -26,7 +26,11 @@ import 'package:process/process.dart';
import 'common.dart';
final Generator kNoColorTerminalPlatform = () => FakePlatform.fromPlatform(const LocalPlatform())..stdoutSupportsAnsi = false;
final Generator kNoColorTerminalPlatform = () {
return FakePlatform.fromPlatform(
const LocalPlatform()
)..stdoutSupportsAnsi = false;
};
class MockApplicationPackageStore extends ApplicationPackageStore {
MockApplicationPackageStore() : super(
......@@ -36,7 +40,7 @@ class MockApplicationPackageStore extends ApplicationPackageStore {
versionCode: 1,
launchActivity: 'io.flutter.android.mock.MockActivity',
),
iOS: BuildableIOSApp(MockIosProject())
iOS: BuildableIOSApp(MockIosProject(), MockIosProject.bundleId)
);
}
......@@ -513,8 +517,10 @@ class MockPollingDeviceDiscovery extends PollingDeviceDiscovery {
}
class MockIosProject extends Mock implements IosProject {
static const String bundleId = 'com.example.test';
@override
String get productBundleIdentifier => 'com.example.test';
Future<String> get productBundleIdentifier async => bundleId;
@override
String get hostAppBundleName => 'Runner.app';
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment