Unverified Commit 7e60a65f authored by Emmanuel Garcia's avatar Emmanuel Garcia Committed by GitHub

Don't read AndroidManifest.xml if it doesn't exit (#43669)

parent 53dcf92f
...@@ -361,8 +361,11 @@ List<Map<String, dynamic>> _extractPlatformMaps(List<Plugin> plugins, String typ ...@@ -361,8 +361,11 @@ List<Map<String, dynamic>> _extractPlatformMaps(List<Plugin> plugins, String typ
/// [project] is using. /// [project] is using.
String _getAndroidEmbeddingVersion(FlutterProject project) { String _getAndroidEmbeddingVersion(FlutterProject project) {
assert(project.android != null); assert(project.android != null);
final File androidManifest = project.android.appManifestFile; final File androidManifest = project.android.appManifestFile;
assert(androidManifest.existsSync()); if (androidManifest == null || !androidManifest.existsSync()) {
return '1';
}
xml.XmlDocument document; xml.XmlDocument document;
try { try {
document = xml.parse(androidManifest.readAsStringSync()); document = xml.parse(androidManifest.readAsStringSync());
......
...@@ -16,434 +16,450 @@ import '../src/common.dart'; ...@@ -16,434 +16,450 @@ import '../src/common.dart';
import '../src/context.dart'; import '../src/context.dart';
void main() { void main() {
FileSystem fs; group('plugins', () {
MockFlutterProject flutterProject; FileSystem fs;
MockIosProject iosProject; MockFlutterProject flutterProject;
MockMacOSProject macosProject; MockIosProject iosProject;
MockAndroidProject androidProject; MockMacOSProject macosProject;
MockWebProject webProject; MockAndroidProject androidProject;
File packagesFile; MockWebProject webProject;
Directory dummyPackageDirectory; File packagesFile;
Directory dummyPackageDirectory;
setUp(() async {
fs = MemoryFileSystem(); setUp(() async {
fs = MemoryFileSystem();
// Add basic properties to the Flutter project and subprojects
flutterProject = MockFlutterProject(); // Add basic properties to the Flutter project and subprojects
when(flutterProject.directory).thenReturn(fs.directory('/')); flutterProject = MockFlutterProject();
when(flutterProject.flutterPluginsFile).thenReturn(flutterProject.directory.childFile('.plugins')); when(flutterProject.directory).thenReturn(fs.directory('/'));
iosProject = MockIosProject(); when(flutterProject.flutterPluginsFile).thenReturn(flutterProject.directory.childFile('.plugins'));
when(flutterProject.ios).thenReturn(iosProject); iosProject = MockIosProject();
when(iosProject.pluginRegistrantHost).thenReturn(flutterProject.directory.childDirectory('Runner')); when(flutterProject.ios).thenReturn(iosProject);
when(iosProject.podfile).thenReturn(flutterProject.directory.childDirectory('ios').childFile('Podfile')); when(iosProject.pluginRegistrantHost).thenReturn(flutterProject.directory.childDirectory('Runner'));
when(iosProject.podManifestLock).thenReturn(flutterProject.directory.childDirectory('ios').childFile('Podfile.lock')); when(iosProject.podfile).thenReturn(flutterProject.directory.childDirectory('ios').childFile('Podfile'));
macosProject = MockMacOSProject(); when(iosProject.podManifestLock).thenReturn(flutterProject.directory.childDirectory('ios').childFile('Podfile.lock'));
when(flutterProject.macos).thenReturn(macosProject); macosProject = MockMacOSProject();
when(macosProject.podfile).thenReturn(flutterProject.directory.childDirectory('macos').childFile('Podfile')); when(flutterProject.macos).thenReturn(macosProject);
when(macosProject.podManifestLock).thenReturn(flutterProject.directory.childDirectory('macos').childFile('Podfile.lock')); when(macosProject.podfile).thenReturn(flutterProject.directory.childDirectory('macos').childFile('Podfile'));
androidProject = MockAndroidProject(); when(macosProject.podManifestLock).thenReturn(flutterProject.directory.childDirectory('macos').childFile('Podfile.lock'));
when(flutterProject.android).thenReturn(androidProject); androidProject = MockAndroidProject();
when(androidProject.pluginRegistrantHost).thenReturn(flutterProject.directory.childDirectory('android').childDirectory('app')); when(flutterProject.android).thenReturn(androidProject);
when(androidProject.hostAppGradleRoot).thenReturn(flutterProject.directory.childDirectory('android')); when(androidProject.pluginRegistrantHost).thenReturn(flutterProject.directory.childDirectory('android').childDirectory('app'));
webProject = MockWebProject(); when(androidProject.hostAppGradleRoot).thenReturn(flutterProject.directory.childDirectory('android'));
when(flutterProject.web).thenReturn(webProject); webProject = MockWebProject();
when(webProject.libDirectory).thenReturn(flutterProject.directory.childDirectory('lib')); when(flutterProject.web).thenReturn(webProject);
when(webProject.existsSync()).thenReturn(true); when(webProject.libDirectory).thenReturn(flutterProject.directory.childDirectory('lib'));
when(webProject.existsSync()).thenReturn(true);
// Set up a simple .packages file for all the tests to use, pointing to one package.
dummyPackageDirectory = fs.directory('/pubcache/apackage/lib/'); // Set up a simple .packages file for all the tests to use, pointing to one package.
packagesFile = fs.file(fs.path.join(flutterProject.directory.path, PackageMap.globalPackagesPath)); dummyPackageDirectory = fs.directory('/pubcache/apackage/lib/');
packagesFile..createSync(recursive: true) packagesFile = fs.file(fs.path.join(flutterProject.directory.path, PackageMap.globalPackagesPath));
..writeAsStringSync('apackage:file://${dummyPackageDirectory.path}'); packagesFile..createSync(recursive: true)
}); ..writeAsStringSync('apackage:file://${dummyPackageDirectory.path}');
// Makes the dummy package pointed to by packagesFile look like a plugin.
void configureDummyPackageAsPlugin() {
dummyPackageDirectory.parent.childFile('pubspec.yaml')..createSync(recursive: true)..writeAsStringSync('''
flutter:
plugin:
platforms:
ios:
pluginClass: FLESomePlugin
''');
}
// Creates the files that would indicate that pod install has run for the
// given project.
void simulatePodInstallRun(XcodeBasedProject project) {
project.podManifestLock.createSync(recursive: true);
}
group('refreshPlugins', () {
testUsingContext('Refreshing the plugin list is a no-op when the plugins list stays empty', () {
refreshPluginsList(flutterProject);
expect(flutterProject.flutterPluginsFile.existsSync(), false);
}, overrides: <Type, Generator>{
FileSystem: () => fs,
ProcessManager: () => FakeProcessManager.any(),
});
testUsingContext('Refreshing the plugin list deletes the plugin file when there were plugins but no longer are', () {
flutterProject.flutterPluginsFile.createSync();
when(iosProject.existsSync()).thenReturn(false);
when(macosProject.existsSync()).thenReturn(false);
refreshPluginsList(flutterProject);
expect(flutterProject.flutterPluginsFile.existsSync(), false);
}, overrides: <Type, Generator>{
FileSystem: () => fs,
ProcessManager: () => FakeProcessManager.any(),
}); });
testUsingContext('Refreshing the plugin list creates a plugin directory when there are plugins', () { // Makes the dummy package pointed to by packagesFile look like a plugin.
configureDummyPackageAsPlugin(); void configureDummyPackageAsPlugin() {
when(iosProject.existsSync()).thenReturn(false); dummyPackageDirectory.parent.childFile('pubspec.yaml')..createSync(recursive: true)..writeAsStringSync('''
when(macosProject.existsSync()).thenReturn(false); flutter:
refreshPluginsList(flutterProject); plugin:
expect(flutterProject.flutterPluginsFile.existsSync(), true); platforms:
}, overrides: <Type, Generator>{ ios:
FileSystem: () => fs, pluginClass: FLESomePlugin
ProcessManager: () => FakeProcessManager.any(), ''');
}
// Creates the files that would indicate that pod install has run for the
// given project.
void simulatePodInstallRun(XcodeBasedProject project) {
project.podManifestLock.createSync(recursive: true);
}
group('refreshPlugins', () {
testUsingContext('Refreshing the plugin list is a no-op when the plugins list stays empty', () {
refreshPluginsList(flutterProject);
expect(flutterProject.flutterPluginsFile.existsSync(), false);
}, overrides: <Type, Generator>{
FileSystem: () => fs,
ProcessManager: () => FakeProcessManager.any(),
});
testUsingContext('Refreshing the plugin list deletes the plugin file when there were plugins but no longer are', () {
flutterProject.flutterPluginsFile.createSync();
when(iosProject.existsSync()).thenReturn(false);
when(macosProject.existsSync()).thenReturn(false);
refreshPluginsList(flutterProject);
expect(flutterProject.flutterPluginsFile.existsSync(), false);
}, overrides: <Type, Generator>{
FileSystem: () => fs,
ProcessManager: () => FakeProcessManager.any(),
});
testUsingContext('Refreshing the plugin list creates a plugin directory when there are plugins', () {
configureDummyPackageAsPlugin();
when(iosProject.existsSync()).thenReturn(false);
when(macosProject.existsSync()).thenReturn(false);
refreshPluginsList(flutterProject);
expect(flutterProject.flutterPluginsFile.existsSync(), true);
}, overrides: <Type, Generator>{
FileSystem: () => fs,
ProcessManager: () => FakeProcessManager.any(),
});
testUsingContext('Changes to the plugin list invalidates the Cocoapod lockfiles', () {
simulatePodInstallRun(iosProject);
simulatePodInstallRun(macosProject);
configureDummyPackageAsPlugin();
when(iosProject.existsSync()).thenReturn(true);
when(macosProject.existsSync()).thenReturn(true);
refreshPluginsList(flutterProject);
expect(iosProject.podManifestLock.existsSync(), false);
expect(macosProject.podManifestLock.existsSync(), false);
}, overrides: <Type, Generator>{
FileSystem: () => fs,
ProcessManager: () => FakeProcessManager.any(),
});
}); });
testUsingContext('Changes to the plugin list invalidates the Cocoapod lockfiles', () { group('injectPlugins', () {
simulatePodInstallRun(iosProject); MockFeatureFlags featureFlags;
simulatePodInstallRun(macosProject); MockXcodeProjectInterpreter xcodeProjectInterpreter;
configureDummyPackageAsPlugin();
when(iosProject.existsSync()).thenReturn(true); const String kAndroidManifestUsingOldEmbedding = '''
when(macosProject.existsSync()).thenReturn(true); <manifest>
refreshPluginsList(flutterProject); <application>
expect(iosProject.podManifestLock.existsSync(), false); </application>
expect(macosProject.podManifestLock.existsSync(), false); </manifest>
}, overrides: <Type, Generator>{ ''';
FileSystem: () => fs, const String kAndroidManifestUsingNewEmbedding = '''
ProcessManager: () => FakeProcessManager.any(), <manifest>
}); <application>
}); <meta-data
android:name="flutterEmbedding"
group('injectPlugins', () { android:value="2" />
MockFeatureFlags featureFlags; </application>
MockXcodeProjectInterpreter xcodeProjectInterpreter; </manifest>
''';
const String kAndroidManifestUsingOldEmbedding = '''
<manifest> setUp(() {
<application> featureFlags = MockFeatureFlags();
</application> when(featureFlags.isLinuxEnabled).thenReturn(false);
</manifest> when(featureFlags.isMacOSEnabled).thenReturn(false);
'''; when(featureFlags.isWindowsEnabled).thenReturn(false);
const String kAndroidManifestUsingNewEmbedding = ''' when(featureFlags.isWebEnabled).thenReturn(false);
<manifest>
<application> xcodeProjectInterpreter = MockXcodeProjectInterpreter();
<meta-data when(xcodeProjectInterpreter.isInstalled).thenReturn(false);
android:name="flutterEmbedding" });
android:value="2" />
</application> testUsingContext('Registrant uses old embedding in app project', () async {
</manifest> when(flutterProject.isModule).thenReturn(false);
''';
final File androidManifest = flutterProject.directory
setUp(() { .childDirectory('android')
featureFlags = MockFeatureFlags(); .childFile('AndroidManifest.xml')
when(featureFlags.isLinuxEnabled).thenReturn(false); ..createSync(recursive: true)
when(featureFlags.isMacOSEnabled).thenReturn(false); ..writeAsStringSync(kAndroidManifestUsingOldEmbedding);
when(featureFlags.isWindowsEnabled).thenReturn(false); when(androidProject.appManifestFile).thenReturn(androidManifest);
when(featureFlags.isWebEnabled).thenReturn(false);
await injectPlugins(flutterProject);
xcodeProjectInterpreter = MockXcodeProjectInterpreter();
when(xcodeProjectInterpreter.isInstalled).thenReturn(false); final File registrant = flutterProject.directory
}); .childDirectory(fs.path.join('android', 'app', 'src', 'main', 'java', 'io', 'flutter', 'plugins'))
.childFile('GeneratedPluginRegistrant.java');
testUsingContext('Registrant uses old embedding in app project', () async {
when(flutterProject.isModule).thenReturn(false); expect(registrant.existsSync(), isTrue);
expect(registrant.readAsStringSync(), contains('package io.flutter.plugins'));
final File androidManifest = flutterProject.directory expect(registrant.readAsStringSync(), contains('class GeneratedPluginRegistrant'));
.childDirectory('android') }, overrides: <Type, Generator>{
.childFile('AndroidManifest.xml') FileSystem: () => fs,
..createSync(recursive: true) ProcessManager: () => FakeProcessManager.any(),
..writeAsStringSync(kAndroidManifestUsingOldEmbedding); FeatureFlags: () => featureFlags,
when(androidProject.appManifestFile).thenReturn(androidManifest); });
await injectPlugins(flutterProject); testUsingContext('Registrant uses new embedding if app uses new embedding', () async {
when(flutterProject.isModule).thenReturn(false);
final File registrant = flutterProject.directory
.childDirectory(fs.path.join('android', 'app', 'src', 'main', 'java', 'io', 'flutter', 'plugins')) final File androidManifest = flutterProject.directory
.childFile('GeneratedPluginRegistrant.java'); .childDirectory('android')
.childFile('AndroidManifest.xml')
expect(registrant.existsSync(), isTrue); ..createSync(recursive: true)
expect(registrant.readAsStringSync(), contains('package io.flutter.plugins')); ..writeAsStringSync(kAndroidManifestUsingNewEmbedding);
expect(registrant.readAsStringSync(), contains('class GeneratedPluginRegistrant')); when(androidProject.appManifestFile).thenReturn(androidManifest);
}, overrides: <Type, Generator>{
FileSystem: () => fs, await injectPlugins(flutterProject);
ProcessManager: () => FakeProcessManager.any(),
FeatureFlags: () => featureFlags, final File registrant = flutterProject.directory
}); .childDirectory(fs.path.join('android', 'app', 'src', 'main', 'java', 'dev', 'flutter', 'plugins'))
.childFile('GeneratedPluginRegistrant.java');
testUsingContext('Registrant uses new embedding if app uses new embedding', () async {
when(flutterProject.isModule).thenReturn(false); expect(registrant.existsSync(), isTrue);
expect(registrant.readAsStringSync(), contains('package dev.flutter.plugins'));
final File androidManifest = flutterProject.directory expect(registrant.readAsStringSync(), contains('class GeneratedPluginRegistrant'));
.childDirectory('android') }, overrides: <Type, Generator>{
.childFile('AndroidManifest.xml') FileSystem: () => fs,
..createSync(recursive: true) ProcessManager: () => FakeProcessManager.any(),
..writeAsStringSync(kAndroidManifestUsingNewEmbedding); FeatureFlags: () => featureFlags,
when(androidProject.appManifestFile).thenReturn(androidManifest); });
await injectPlugins(flutterProject); testUsingContext('Registrant uses shim for plugins using old embedding if app uses new embedding', () async {
when(flutterProject.isModule).thenReturn(false);
final File registrant = flutterProject.directory
.childDirectory(fs.path.join('android', 'app', 'src', 'main', 'java', 'dev', 'flutter', 'plugins')) final File androidManifest = flutterProject.directory
.childFile('GeneratedPluginRegistrant.java'); .childDirectory('android')
.childFile('AndroidManifest.xml')
expect(registrant.existsSync(), isTrue); ..createSync(recursive: true)
expect(registrant.readAsStringSync(), contains('package dev.flutter.plugins')); ..writeAsStringSync(kAndroidManifestUsingNewEmbedding);
expect(registrant.readAsStringSync(), contains('class GeneratedPluginRegistrant')); when(androidProject.appManifestFile).thenReturn(androidManifest);
}, overrides: <Type, Generator>{
FileSystem: () => fs, final Directory pluginUsingJavaAndNewEmbeddingDir =
ProcessManager: () => FakeProcessManager.any(), fs.systemTempDirectory.createTempSync('flutter_plugin_using_java_and_new_embedding_dir.');
FeatureFlags: () => featureFlags, pluginUsingJavaAndNewEmbeddingDir
}); .childFile('pubspec.yaml')
.writeAsStringSync('''
testUsingContext('Registrant uses shim for plugins using old embedding if app uses new embedding', () async { flutter:
when(flutterProject.isModule).thenReturn(false); plugin:
androidPackage: plugin1
final File androidManifest = flutterProject.directory pluginClass: UseNewEmbedding
.childDirectory('android') ''');
.childFile('AndroidManifest.xml') pluginUsingJavaAndNewEmbeddingDir
..createSync(recursive: true) .childDirectory('android')
..writeAsStringSync(kAndroidManifestUsingNewEmbedding); .childDirectory('src')
when(androidProject.appManifestFile).thenReturn(androidManifest); .childDirectory('main')
.childDirectory('java')
final Directory pluginUsingJavaAndNewEmbeddingDir = .childDirectory('plugin1')
fs.systemTempDirectory.createTempSync('flutter_plugin_using_java_and_new_embedding_dir.'); .childFile('UseNewEmbedding.java')
pluginUsingJavaAndNewEmbeddingDir ..createSync(recursive: true)
.childFile('pubspec.yaml') ..writeAsStringSync('import io.flutter.embedding.engine.plugins.FlutterPlugin;');
.writeAsStringSync('''
flutter: final Directory pluginUsingKotlinAndNewEmbeddingDir =
plugin: fs.systemTempDirectory.createTempSync('flutter_plugin_using_kotlin_and_new_embedding_dir.');
androidPackage: plugin1 pluginUsingKotlinAndNewEmbeddingDir
pluginClass: UseNewEmbedding .childFile('pubspec.yaml')
'''); .writeAsStringSync('''
pluginUsingJavaAndNewEmbeddingDir flutter:
.childDirectory('android') plugin:
.childDirectory('src') androidPackage: plugin2
.childDirectory('main') pluginClass: UseNewEmbedding
.childDirectory('java') ''');
.childDirectory('plugin1') pluginUsingKotlinAndNewEmbeddingDir
.childFile('UseNewEmbedding.java') .childDirectory('android')
..createSync(recursive: true) .childDirectory('src')
..writeAsStringSync('import io.flutter.embedding.engine.plugins.FlutterPlugin;'); .childDirectory('main')
.childDirectory('kotlin')
final Directory pluginUsingKotlinAndNewEmbeddingDir = .childDirectory('plugin2')
fs.systemTempDirectory.createTempSync('flutter_plugin_using_kotlin_and_new_embedding_dir.'); .childFile('UseNewEmbedding.kt')
pluginUsingKotlinAndNewEmbeddingDir ..createSync(recursive: true)
.childFile('pubspec.yaml') ..writeAsStringSync('import io.flutter.embedding.engine.plugins.FlutterPlugin');
.writeAsStringSync('''
flutter: final Directory pluginUsingOldEmbeddingDir =
plugin: fs.systemTempDirectory.createTempSync('flutter_plugin_using_old_embedding_dir.');
androidPackage: plugin2 pluginUsingOldEmbeddingDir
pluginClass: UseNewEmbedding .childFile('pubspec.yaml')
'''); .writeAsStringSync('''
pluginUsingKotlinAndNewEmbeddingDir flutter:
.childDirectory('android') plugin:
.childDirectory('src') androidPackage: plugin3
.childDirectory('main') pluginClass: UseOldEmbedding
.childDirectory('kotlin') ''');
.childDirectory('plugin2') pluginUsingOldEmbeddingDir
.childFile('UseNewEmbedding.kt') .childDirectory('android')
..createSync(recursive: true) .childDirectory('src')
..writeAsStringSync('import io.flutter.embedding.engine.plugins.FlutterPlugin'); .childDirectory('main')
.childDirectory('java')
final Directory pluginUsingOldEmbeddingDir = .childDirectory('plugin3')
fs.systemTempDirectory.createTempSync('flutter_plugin_using_old_embedding_dir.'); .childFile('UseOldEmbedding.java')
pluginUsingOldEmbeddingDir ..createSync(recursive: true);
.childFile('pubspec.yaml')
.writeAsStringSync(''' flutterProject.directory
flutter: .childFile('.packages')
plugin: .writeAsStringSync('''
androidPackage: plugin3
pluginClass: UseOldEmbedding
''');
pluginUsingOldEmbeddingDir
.childDirectory('android')
.childDirectory('src')
.childDirectory('main')
.childDirectory('java')
.childDirectory('plugin3')
.childFile('UseOldEmbedding.java')
..createSync(recursive: true);
flutterProject.directory
.childFile('.packages')
.writeAsStringSync('''
plugin1:${pluginUsingJavaAndNewEmbeddingDir.childDirectory('lib').uri.toString()} plugin1:${pluginUsingJavaAndNewEmbeddingDir.childDirectory('lib').uri.toString()}
plugin2:${pluginUsingKotlinAndNewEmbeddingDir.childDirectory('lib').uri.toString()} plugin2:${pluginUsingKotlinAndNewEmbeddingDir.childDirectory('lib').uri.toString()}
plugin3:${pluginUsingOldEmbeddingDir.childDirectory('lib').uri.toString()} plugin3:${pluginUsingOldEmbeddingDir.childDirectory('lib').uri.toString()}
'''); ''');
await injectPlugins(flutterProject); await injectPlugins(flutterProject);
final File registrant = flutterProject.directory final File registrant = flutterProject.directory
.childDirectory(fs.path.join('android', 'app', 'src', 'main', 'java', 'dev', 'flutter', 'plugins')) .childDirectory(fs.path.join('android', 'app', 'src', 'main', 'java', 'dev', 'flutter', 'plugins'))
.childFile('GeneratedPluginRegistrant.java'); .childFile('GeneratedPluginRegistrant.java');
expect(registrant.readAsStringSync(), expect(registrant.readAsStringSync(),
contains('flutterEngine.getPlugins().add(new plugin1.UseNewEmbedding());')); contains('flutterEngine.getPlugins().add(new plugin1.UseNewEmbedding());'));
expect(registrant.readAsStringSync(), expect(registrant.readAsStringSync(),
contains('flutterEngine.getPlugins().add(new plugin2.UseNewEmbedding());')); contains('flutterEngine.getPlugins().add(new plugin2.UseNewEmbedding());'));
expect(registrant.readAsStringSync(), expect(registrant.readAsStringSync(),
contains('plugin3.UseOldEmbedding.registerWith(shimPluginRegistry.registrarFor("plugin3.UseOldEmbedding"));')); contains('plugin3.UseOldEmbedding.registerWith(shimPluginRegistry.registrarFor("plugin3.UseOldEmbedding"));'));
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
FileSystem: () => fs, FileSystem: () => fs,
ProcessManager: () => FakeProcessManager.any(), ProcessManager: () => FakeProcessManager.any(),
FeatureFlags: () => featureFlags, FeatureFlags: () => featureFlags,
XcodeProjectInterpreter: () => xcodeProjectInterpreter, XcodeProjectInterpreter: () => xcodeProjectInterpreter,
}); });
testUsingContext('Registrant doesn\'t use new embedding if app doesn\'t use new embedding', () async { testUsingContext('Registrant doesn\'t use new embedding if app doesn\'t use new embedding', () async {
when(flutterProject.isModule).thenReturn(false); when(flutterProject.isModule).thenReturn(false);
final File androidManifest = flutterProject.directory final File androidManifest = flutterProject.directory
.childDirectory('android') .childDirectory('android')
.childFile('AndroidManifest.xml') .childFile('AndroidManifest.xml')
..createSync(recursive: true) ..createSync(recursive: true)
..writeAsStringSync(kAndroidManifestUsingOldEmbedding); ..writeAsStringSync(kAndroidManifestUsingOldEmbedding);
when(androidProject.appManifestFile).thenReturn(androidManifest); when(androidProject.appManifestFile).thenReturn(androidManifest);
await injectPlugins(flutterProject); await injectPlugins(flutterProject);
final File registrant = flutterProject.directory final File registrant = flutterProject.directory
.childDirectory(fs.path.join('android', 'app', 'src', 'main', 'java', 'io', 'flutter', 'plugins')) .childDirectory(fs.path.join('android', 'app', 'src', 'main', 'java', 'io', 'flutter', 'plugins'))
.childFile('GeneratedPluginRegistrant.java'); .childFile('GeneratedPluginRegistrant.java');
expect(registrant.existsSync(), isTrue); expect(registrant.existsSync(), isTrue);
expect(registrant.readAsStringSync(), contains('package io.flutter.plugins')); expect(registrant.readAsStringSync(), contains('package io.flutter.plugins'));
expect(registrant.readAsStringSync(), contains('class GeneratedPluginRegistrant')); expect(registrant.readAsStringSync(), contains('class GeneratedPluginRegistrant'));
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
FileSystem: () => fs, FileSystem: () => fs,
ProcessManager: () => FakeProcessManager.any(), ProcessManager: () => FakeProcessManager.any(),
FeatureFlags: () => featureFlags, FeatureFlags: () => featureFlags,
}); });
testUsingContext('Registrant uses old embedding in module project', () async { testUsingContext('Registrant uses old embedding in module project', () async {
when(flutterProject.isModule).thenReturn(true); when(flutterProject.isModule).thenReturn(true);
final File androidManifest = flutterProject.directory final File androidManifest = flutterProject.directory
.childDirectory('android') .childDirectory('android')
.childFile('AndroidManifest.xml') .childFile('AndroidManifest.xml')
..createSync(recursive: true) ..createSync(recursive: true)
..writeAsStringSync(kAndroidManifestUsingOldEmbedding); ..writeAsStringSync(kAndroidManifestUsingOldEmbedding);
when(androidProject.appManifestFile).thenReturn(androidManifest); when(androidProject.appManifestFile).thenReturn(androidManifest);
await injectPlugins(flutterProject); await injectPlugins(flutterProject);
final File registrant = flutterProject.directory final File registrant = flutterProject.directory
.childDirectory(fs.path.join('android', 'app', 'src', 'main', 'java', 'io', 'flutter', 'plugins')) .childDirectory(fs.path.join('android', 'app', 'src', 'main', 'java', 'io', 'flutter', 'plugins'))
.childFile('GeneratedPluginRegistrant.java'); .childFile('GeneratedPluginRegistrant.java');
expect(registrant.existsSync(), isTrue); expect(registrant.existsSync(), isTrue);
expect(registrant.readAsStringSync(), contains('package io.flutter.plugins')); expect(registrant.readAsStringSync(), contains('package io.flutter.plugins'));
expect(registrant.readAsStringSync(), contains('class GeneratedPluginRegistrant')); expect(registrant.readAsStringSync(), contains('class GeneratedPluginRegistrant'));
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
FileSystem: () => fs, FileSystem: () => fs,
ProcessManager: () => FakeProcessManager.any(), ProcessManager: () => FakeProcessManager.any(),
FeatureFlags: () => featureFlags, FeatureFlags: () => featureFlags,
}); });
testUsingContext('Registrant uses new embedding if module uses new embedding', () async { testUsingContext('Registrant uses new embedding if module uses new embedding', () async {
when(flutterProject.isModule).thenReturn(true); when(flutterProject.isModule).thenReturn(true);
final File androidManifest = flutterProject.directory final File androidManifest = flutterProject.directory
.childDirectory('android') .childDirectory('android')
.childFile('AndroidManifest.xml') .childFile('AndroidManifest.xml')
..createSync(recursive: true) ..createSync(recursive: true)
..writeAsStringSync(kAndroidManifestUsingNewEmbedding); ..writeAsStringSync(kAndroidManifestUsingNewEmbedding);
when(androidProject.appManifestFile).thenReturn(androidManifest); when(androidProject.appManifestFile).thenReturn(androidManifest);
await injectPlugins(flutterProject); await injectPlugins(flutterProject);
final File registrant = flutterProject.directory final File registrant = flutterProject.directory
.childDirectory(fs.path.join('android', 'app', 'src', 'main', 'java', 'dev', 'flutter', 'plugins')) .childDirectory(fs.path.join('android', 'app', 'src', 'main', 'java', 'dev', 'flutter', 'plugins'))
.childFile('GeneratedPluginRegistrant.java'); .childFile('GeneratedPluginRegistrant.java');
expect(registrant.existsSync(), isTrue); expect(registrant.existsSync(), isTrue);
expect(registrant.readAsStringSync(), contains('package dev.flutter.plugins')); expect(registrant.readAsStringSync(), contains('package dev.flutter.plugins'));
expect(registrant.readAsStringSync(), contains('class GeneratedPluginRegistrant')); expect(registrant.readAsStringSync(), contains('class GeneratedPluginRegistrant'));
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
FileSystem: () => fs, FileSystem: () => fs,
ProcessManager: () => FakeProcessManager.any(), ProcessManager: () => FakeProcessManager.any(),
FeatureFlags: () => featureFlags, FeatureFlags: () => featureFlags,
}); });
testUsingContext('Registrant doesn\'t use new embedding if module doesn\'t use new embedding', () async { testUsingContext('Registrant doesn\'t use new embedding if module doesn\'t use new embedding', () async {
when(flutterProject.isModule).thenReturn(true); when(flutterProject.isModule).thenReturn(true);
final File androidManifest = flutterProject.directory final File androidManifest = flutterProject.directory
.childDirectory('android') .childDirectory('android')
.childFile('AndroidManifest.xml') .childFile('AndroidManifest.xml')
..createSync(recursive: true) ..createSync(recursive: true)
..writeAsStringSync(kAndroidManifestUsingOldEmbedding); ..writeAsStringSync(kAndroidManifestUsingOldEmbedding);
when(androidProject.appManifestFile).thenReturn(androidManifest); when(androidProject.appManifestFile).thenReturn(androidManifest);
await injectPlugins(flutterProject); await injectPlugins(flutterProject);
final File registrant = flutterProject.directory final File registrant = flutterProject.directory
.childDirectory(fs.path.join('android', 'app', 'src', 'main', 'java', 'io', 'flutter', 'plugins')) .childDirectory(fs.path.join('android', 'app', 'src', 'main', 'java', 'io', 'flutter', 'plugins'))
.childFile('GeneratedPluginRegistrant.java'); .childFile('GeneratedPluginRegistrant.java');
expect(registrant.existsSync(), isTrue); expect(registrant.existsSync(), isTrue);
expect(registrant.readAsStringSync(), contains('package io.flutter.plugins')); expect(registrant.readAsStringSync(), contains('package io.flutter.plugins'));
expect(registrant.readAsStringSync(), contains('class GeneratedPluginRegistrant')); expect(registrant.readAsStringSync(), contains('class GeneratedPluginRegistrant'));
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
FileSystem: () => fs, FileSystem: () => fs,
ProcessManager: () => FakeProcessManager.any(), ProcessManager: () => FakeProcessManager.any(),
FeatureFlags: () => featureFlags, FeatureFlags: () => featureFlags,
}); });
testUsingContext('Does not throw when AndroidManifest.xml is not found', () async {
when(flutterProject.isModule).thenReturn(false);
final File manifest = MockFile();
when(manifest.existsSync()).thenReturn(false);
when(androidProject.appManifestFile).thenReturn(manifest);
await injectPlugins(flutterProject);
}, overrides: <Type, Generator>{
FileSystem: () => fs,
ProcessManager: () => FakeProcessManager.any(),
});
testUsingContext('Registrant for web doesn\'t escape slashes in imports', () async {
when(flutterProject.isModule).thenReturn(true);
when(featureFlags.isWebEnabled).thenReturn(true);
// injectPlugins will crash if there is no AndroidManifest
final File androidManifest = flutterProject.directory
.childDirectory('android')
.childFile('AndroidManifest.xml')
..createSync(recursive: true)
..writeAsStringSync(kAndroidManifestUsingOldEmbedding);
when(androidProject.appManifestFile).thenReturn(androidManifest);
final Directory webPluginWithNestedFile =
fs.systemTempDirectory.createTempSync('web_plugin_with_nested');
webPluginWithNestedFile.childFile('pubspec.yaml').writeAsStringSync('''
flutter:
plugin:
platforms:
web:
pluginClass: WebPlugin
fileName: src/web_plugin.dart
''');
webPluginWithNestedFile
.childDirectory('lib')
.childDirectory('src')
.childFile('web_plugin.dart')
..createSync(recursive: true);
testUsingContext('Registrant for web doesn\'t escape slashes in imports', () async { flutterProject.directory
when(flutterProject.isModule).thenReturn(true); .childFile('.packages')
when(featureFlags.isWebEnabled).thenReturn(true); .writeAsStringSync('''
// injectPlugins will crash if there is no AndroidManifest
final File androidManifest = flutterProject.directory
.childDirectory('android')
.childFile('AndroidManifest.xml')
..createSync(recursive: true)
..writeAsStringSync(kAndroidManifestUsingOldEmbedding);
when(androidProject.appManifestFile).thenReturn(androidManifest);
final Directory webPluginWithNestedFile =
fs.systemTempDirectory.createTempSync('web_plugin_with_nested');
webPluginWithNestedFile.childFile('pubspec.yaml').writeAsStringSync('''
flutter:
plugin:
platforms:
web:
pluginClass: WebPlugin
fileName: src/web_plugin.dart
''');
webPluginWithNestedFile
.childDirectory('lib')
.childDirectory('src')
.childFile('web_plugin.dart')
..createSync(recursive: true);
flutterProject.directory
.childFile('.packages')
.writeAsStringSync('''
web_plugin_with_nested:${webPluginWithNestedFile.childDirectory('lib').uri.toString()} web_plugin_with_nested:${webPluginWithNestedFile.childDirectory('lib').uri.toString()}
'''); ''');
await injectPlugins(flutterProject); await injectPlugins(flutterProject);
final File registrant = flutterProject.directory final File registrant = flutterProject.directory
.childDirectory('lib') .childDirectory('lib')
.childFile('generated_plugin_registrant.dart'); .childFile('generated_plugin_registrant.dart');
expect(registrant.existsSync(), isTrue); expect(registrant.existsSync(), isTrue);
expect(registrant.readAsStringSync(), contains("import 'package:web_plugin_with_nested/src/web_plugin.dart';")); expect(registrant.readAsStringSync(), contains("import 'package:web_plugin_with_nested/src/web_plugin.dart';"));
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
FileSystem: () => fs, FileSystem: () => fs,
ProcessManager: () => FakeProcessManager.any(), ProcessManager: () => FakeProcessManager.any(),
FeatureFlags: () => featureFlags, FeatureFlags: () => featureFlags,
});
}); });
}); });
} }
...@@ -451,6 +467,7 @@ web_plugin_with_nested:${webPluginWithNestedFile.childDirectory('lib').uri.toStr ...@@ -451,6 +467,7 @@ web_plugin_with_nested:${webPluginWithNestedFile.childDirectory('lib').uri.toStr
class MockAndroidProject extends Mock implements AndroidProject {} class MockAndroidProject extends Mock implements AndroidProject {}
class MockFeatureFlags extends Mock implements FeatureFlags {} class MockFeatureFlags extends Mock implements FeatureFlags {}
class MockFlutterProject extends Mock implements FlutterProject {} class MockFlutterProject extends Mock implements FlutterProject {}
class MockFile extends Mock implements File {}
class MockIosProject extends Mock implements IosProject {} class MockIosProject extends Mock implements IosProject {}
class MockMacOSProject extends Mock implements MacOSProject {} class MockMacOSProject extends Mock implements MacOSProject {}
class MockXcodeProjectInterpreter extends Mock implements XcodeProjectInterpreter {} class MockXcodeProjectInterpreter extends Mock implements XcodeProjectInterpreter {}
......
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