diff --git a/packages/flutter_tools/test/general.shard/macos/application_package_test.dart b/packages/flutter_tools/test/general.shard/macos/application_package_test.dart index 7f21527ccd..42587be74f 100644 --- a/packages/flutter_tools/test/general.shard/macos/application_package_test.dart +++ b/packages/flutter_tools/test/general.shard/macos/application_package_test.dart @@ -9,186 +9,147 @@ import 'dart:convert'; import 'package:file/file.dart'; import 'package:file/memory.dart'; import 'package:flutter_tools/src/base/file_system.dart'; +import 'package:flutter_tools/src/base/logger.dart'; import 'package:flutter_tools/src/base/os.dart'; -import 'package:flutter_tools/src/base/platform.dart'; import 'package:flutter_tools/src/base/utils.dart'; -import 'package:flutter_tools/src/globals_null_migrated.dart' as globals; import 'package:flutter_tools/src/ios/plist_parser.dart'; import 'package:flutter_tools/src/macos/application_package.dart'; -import 'package:mockito/mockito.dart'; +import 'package:test/fake.dart'; import '../../src/common.dart'; import '../../src/context.dart'; void main() { - group('PrebuiltMacOSApp', () { - MockOperatingSystemUtils os; +group('PrebuiltMacOSApp', () { + FakeOperatingSystemUtils os; + FileSystem fileSystem; + BufferLogger logger; + final Map overrides = { - FileSystem: () => MemoryFileSystem.test(), + FileSystem: () => fileSystem, ProcessManager: () => FakeProcessManager.any(), - PlistParser: () => FakePlistUtils(), - Platform: _kNoColorTerminalPlatform, + PlistParser: () => FakePlistUtils(fileSystem), OperatingSystemUtils: () => os, + Logger: () => logger, }; setUp(() { - os = MockOperatingSystemUtils(); + fileSystem = MemoryFileSystem.test(); + os = FakeOperatingSystemUtils(); + logger = BufferLogger.test(); }); testUsingContext('Error on non-existing file', () { - final PrebuiltMacOSApp macosApp = - MacOSApp.fromPrebuiltApp(globals.fs.file('not_existing.app')) - as PrebuiltMacOSApp; + final PrebuiltMacOSApp macosApp = MacOSApp.fromPrebuiltApp(fileSystem.file('not_existing.app')) as PrebuiltMacOSApp; + expect(macosApp, isNull); - expect( - testLogger.errorText, - 'File "not_existing.app" does not exist.\n', - ); + expect(logger.errorText, contains('File "not_existing.app" does not exist.')); }, overrides: overrides); testUsingContext('Error on non-app-bundle folder', () { - globals.fs.directory('regular_folder').createSync(); - final PrebuiltMacOSApp macosApp = - MacOSApp.fromPrebuiltApp(globals.fs.file('regular_folder')) - as PrebuiltMacOSApp; + fileSystem.directory('regular_folder').createSync(); + final PrebuiltMacOSApp macosApp = MacOSApp.fromPrebuiltApp(fileSystem.file('regular_folder')) as PrebuiltMacOSApp; + expect(macosApp, isNull); - expect(testLogger.errorText, - 'Folder "regular_folder" is not an app bundle.\n'); + expect(logger.errorText, contains('Folder "regular_folder" is not an app bundle.')); }, overrides: overrides); testUsingContext('Error on no info.plist', () { - globals.fs.directory('bundle.app').createSync(); - final PrebuiltMacOSApp macosApp = - MacOSApp.fromPrebuiltApp(globals.fs.file('bundle.app')) - as PrebuiltMacOSApp; + fileSystem.directory('bundle.app').createSync(); + final PrebuiltMacOSApp macosApp = MacOSApp.fromPrebuiltApp(fileSystem.file('bundle.app')) as PrebuiltMacOSApp; + expect(macosApp, isNull); - expect( - testLogger.errorText, - 'Invalid prebuilt macOS app. Does not contain Info.plist.\n', - ); + expect(logger.errorText, contains('Invalid prebuilt macOS app. Does not contain Info.plist.')); }, overrides: overrides); testUsingContext('Error on info.plist missing bundle identifier', () { - final String contentsDirectory = - globals.fs.path.join('bundle.app', 'Contents'); - globals.fs.directory(contentsDirectory).createSync(recursive: true); - globals.fs - .file(globals.fs.path.join('bundle.app', 'Contents', 'Info.plist')) - .writeAsStringSync(badPlistData); - final PrebuiltMacOSApp macosApp = - MacOSApp.fromPrebuiltApp(globals.fs.file('bundle.app')) - as PrebuiltMacOSApp; + final String contentsDirectory = fileSystem.path.join('bundle.app', 'Contents'); + fileSystem.directory(contentsDirectory).createSync(recursive: true); + fileSystem + .file(fileSystem.path.join('bundle.app', 'Contents', 'Info.plist')) + .writeAsStringSync(badPlistData); + final PrebuiltMacOSApp macosApp = MacOSApp.fromPrebuiltApp(fileSystem.file('bundle.app')) as PrebuiltMacOSApp; + expect(macosApp, isNull); - expect( - testLogger.errorText, - contains( - 'Invalid prebuilt macOS app. Info.plist does not contain bundle identifier\n'), - ); + expect(logger.errorText, contains('Invalid prebuilt macOS app. Info.plist does not contain bundle identifier')); }, overrides: overrides); testUsingContext('Error on info.plist missing executable', () { - final String contentsDirectory = - globals.fs.path.join('bundle.app', 'Contents'); - globals.fs.directory(contentsDirectory).createSync(recursive: true); - globals.fs - .file(globals.fs.path.join('bundle.app', 'Contents', 'Info.plist')) - .writeAsStringSync(badPlistDataNoExecutable); - final PrebuiltMacOSApp macosApp = - MacOSApp.fromPrebuiltApp(globals.fs.file('bundle.app')) - as PrebuiltMacOSApp; + final String contentsDirectory = fileSystem.path.join('bundle.app', 'Contents'); + fileSystem.directory(contentsDirectory).createSync(recursive: true); + fileSystem + .file(fileSystem.path.join('bundle.app', 'Contents', 'Info.plist')) + .writeAsStringSync(badPlistDataNoExecutable); + final PrebuiltMacOSApp macosApp = MacOSApp.fromPrebuiltApp(fileSystem.file('bundle.app')) as PrebuiltMacOSApp; + expect(macosApp, isNull); - expect( - testLogger.errorText, - contains( - 'Invalid prebuilt macOS app. Info.plist does not contain bundle executable\n'), - ); + expect(logger.errorText, contains('Invalid prebuilt macOS app. Info.plist does not contain bundle executable')); }, overrides: overrides); testUsingContext('Success with app bundle', () { - final String appDirectory = - globals.fs.path.join('bundle.app', 'Contents', 'MacOS'); - globals.fs.directory(appDirectory).createSync(recursive: true); - globals.fs - .file(globals.fs.path.join('bundle.app', 'Contents', 'Info.plist')) - .writeAsStringSync(plistData); - globals.fs - .file(globals.fs.path.join(appDirectory, executableName)) - .createSync(); - final PrebuiltMacOSApp macosApp = - MacOSApp.fromPrebuiltApp(globals.fs.file('bundle.app')) - as PrebuiltMacOSApp; - expect(testLogger.errorText, isEmpty); + final String appDirectory = fileSystem.path.join('bundle.app', 'Contents', 'MacOS'); + fileSystem.directory(appDirectory).createSync(recursive: true); + fileSystem + .file(fileSystem.path.join('bundle.app', 'Contents', 'Info.plist')) + .writeAsStringSync(plistData); + fileSystem + .file(fileSystem.path.join(appDirectory, executableName)) + .createSync(); + final PrebuiltMacOSApp macosApp = MacOSApp.fromPrebuiltApp(fileSystem.file('bundle.app')) as PrebuiltMacOSApp; + + expect(logger.errorText, isEmpty); expect(macosApp.bundleDir.path, 'bundle.app'); expect(macosApp.id, 'fooBundleId'); expect(macosApp.bundleName, 'bundle.app'); }, overrides: overrides); testUsingContext('Bad zipped app, no payload dir', () { - globals.fs.file('app.zip').createSync(); - when(os.unzip(globals.fs.file('app.zip'), any)) - .thenAnswer((Invocation _) {}); - final PrebuiltMacOSApp macosApp = - MacOSApp.fromPrebuiltApp(globals.fs.file('app.zip')) - as PrebuiltMacOSApp; + fileSystem.file('app.zip').createSync(); + final PrebuiltMacOSApp macosApp = MacOSApp.fromPrebuiltApp(fileSystem.file('app.zip')) as PrebuiltMacOSApp; + expect(macosApp, isNull); - expect( - testLogger.errorText, - 'Archive "app.zip" does not contain a single app bundle.\n', - ); + expect(logger.errorText, contains('Archive "app.zip" does not contain a single app bundle.')); }, overrides: overrides); testUsingContext('Bad zipped app, two app bundles', () { - globals.fs.file('app.zip').createSync(); - when(os.unzip(any, any)).thenAnswer((Invocation invocation) { - final File zipFile = invocation.positionalArguments[0] as File; + fileSystem.file('app.zip').createSync(); + os.unzipOverride = (File zipFile, Directory targetDirectory) { if (zipFile.path != 'app.zip') { return; } - final Directory targetDirectory = - invocation.positionalArguments[1] as Directory; - final String bundlePath1 = - globals.fs.path.join(targetDirectory.path, 'bundle1.app'); - final String bundlePath2 = - globals.fs.path.join(targetDirectory.path, 'bundle2.app'); - globals.fs.directory(bundlePath1).createSync(recursive: true); - globals.fs.directory(bundlePath2).createSync(recursive: true); - }); - final PrebuiltMacOSApp macosApp = - MacOSApp.fromPrebuiltApp(globals.fs.file('app.zip')) - as PrebuiltMacOSApp; + final String bundlePath1 = fileSystem.path.join(targetDirectory.path, 'bundle1.app'); + final String bundlePath2 = fileSystem.path.join(targetDirectory.path, 'bundle2.app'); + fileSystem.directory(bundlePath1).createSync(recursive: true); + fileSystem.directory(bundlePath2).createSync(recursive: true); + }; + final PrebuiltMacOSApp macosApp = MacOSApp.fromPrebuiltApp(fileSystem.file('app.zip')) as PrebuiltMacOSApp; + expect(macosApp, isNull); - expect(testLogger.errorText, - 'Archive "app.zip" does not contain a single app bundle.\n'); + expect(logger.errorText, contains('Archive "app.zip" does not contain a single app bundle.')); }, overrides: overrides); testUsingContext('Success with zipped app', () { - globals.fs.file('app.zip').createSync(); - when(os.unzip(any, any)).thenAnswer((Invocation invocation) { - final File zipFile = invocation.positionalArguments[0] as File; + fileSystem.file('app.zip').createSync(); + os.unzipOverride = (File zipFile, Directory targetDirectory) { if (zipFile.path != 'app.zip') { return; } - final Directory targetDirectory = - invocation.positionalArguments[1] as Directory; - final Directory bundleAppContentsDir = globals.fs.directory(globals - .fs.path - .join(targetDirectory.path, 'bundle.app', 'Contents')); + final Directory bundleAppContentsDir = fileSystem.directory(fileSystem.path.join(targetDirectory.path, 'bundle.app', 'Contents')); bundleAppContentsDir.createSync(recursive: true); - globals.fs - .file(globals.fs.path.join(bundleAppContentsDir.path, 'Info.plist')) - .writeAsStringSync(plistData); - globals.fs - .directory(globals.fs.path.join(bundleAppContentsDir.path, 'MacOS')) - .createSync(); - globals.fs - .file(globals.fs.path - .join(bundleAppContentsDir.path, 'MacOS', executableName)) - .createSync(); - }); - final PrebuiltMacOSApp macosApp = - MacOSApp.fromPrebuiltApp(globals.fs.file('app.zip')) - as PrebuiltMacOSApp; - expect(testLogger.errorText, isEmpty); + fileSystem + .file(fileSystem.path.join(bundleAppContentsDir.path, 'Info.plist')) + .writeAsStringSync(plistData); + fileSystem + .directory(fileSystem.path.join(bundleAppContentsDir.path, 'MacOS')) + .createSync(); + fileSystem + .file(fileSystem.path + .join(bundleAppContentsDir.path, 'MacOS', executableName)) + .createSync(); + }; + final PrebuiltMacOSApp macosApp = MacOSApp.fromPrebuiltApp(fileSystem.file('app.zip')) as PrebuiltMacOSApp; + + expect(logger.errorText, isEmpty); expect(macosApp.bundleDir.path, endsWith('bundle.app')); expect(macosApp.id, 'fooBundleId'); expect(macosApp.bundleName, endsWith('bundle.app')); @@ -196,17 +157,25 @@ void main() { }); } -class MockOperatingSystemUtils extends Mock implements OperatingSystemUtils {} +class FakeOperatingSystemUtils extends Fake implements OperatingSystemUtils { + FakeOperatingSystemUtils(); -FakePlatform _kNoColorTerminalPlatform() => FakePlatform(stdoutSupportsAnsi: false); -final Map noColorTerminalOverride = { - Platform: _kNoColorTerminalPlatform, -}; + void Function(File, Directory) unzipOverride; + + @override + void unzip(File file, Directory targetDirectory) { + unzipOverride?.call(file, targetDirectory); + } +} class FakePlistUtils extends Fake implements PlistParser { + FakePlistUtils(this.fileSystem); + + final FileSystem fileSystem; + @override Map parseFile(String plistFilePath) { - final File file = globals.fs.file(plistFilePath); + final File file = fileSystem.file(plistFilePath); if (!file.existsSync()) { return {}; } diff --git a/packages/flutter_tools/test/general.shard/macos/macos_device_test.dart b/packages/flutter_tools/test/general.shard/macos/macos_device_test.dart index 2eef1fab0d..86584956a8 100644 --- a/packages/flutter_tools/test/general.shard/macos/macos_device_test.dart +++ b/packages/flutter_tools/test/general.shard/macos/macos_device_test.dart @@ -17,7 +17,7 @@ import 'package:flutter_tools/src/macos/application_package.dart'; import 'package:flutter_tools/src/macos/macos_device.dart'; import 'package:flutter_tools/src/macos/macos_workflow.dart'; import 'package:flutter_tools/src/project.dart'; -import 'package:mockito/mockito.dart'; +import 'package:test/fake.dart'; import '../../src/common.dart'; import '../../src/context.dart'; @@ -39,14 +39,14 @@ void main() { fileSystem: MemoryFileSystem.test(), operatingSystemUtils: FakeOperatingSystemUtils(), ); - final MockMacOSApp mockMacOSApp = MockMacOSApp(); + final FakeMacOSApp package = FakeMacOSApp(); expect(await device.targetPlatform, TargetPlatform.darwin); expect(device.name, 'macOS'); - expect(await device.installApp(mockMacOSApp), true); - expect(await device.uninstallApp(mockMacOSApp), true); - expect(await device.isLatestBuildInstalled(mockMacOSApp), true); - expect(await device.isAppInstalled(mockMacOSApp), true); + expect(await device.installApp(package), true); + expect(await device.uninstallApp(package), true); + expect(await device.isLatestBuildInstalled(package), true); + expect(await device.isAppInstalled(package), true); expect(device.category, Category.desktop); expect(device.supportsRuntimeMode(BuildMode.debug), true); @@ -61,7 +61,7 @@ void main() { fileSystem: MemoryFileSystem.test(), processManager: FakeProcessManager.list([ FakeCommand( - command: const ['Example.app'], + command: const ['release/executable'], stdout: 'Hello World', stderr: 'Goodnight, Moon', completer: completer, @@ -70,18 +70,17 @@ void main() { logger: BufferLogger.test(), operatingSystemUtils: FakeOperatingSystemUtils(), ); - final MockMacOSApp mockMacOSApp = MockMacOSApp(); - when(mockMacOSApp.executable(BuildMode.release)).thenReturn('Example.app'); + final FakeMacOSApp package = FakeMacOSApp(); final LaunchResult result = await device.startApp( - mockMacOSApp, + package, debuggingOptions: DebuggingOptions.disabled(BuildInfo.release), prebuiltApplication: true, ); expect(result.started, true); - final DeviceLogReader logReader = device.getLogReader(app: mockMacOSApp); + final DeviceLogReader logReader = device.getLogReader(app: package); expect(logReader.logLines, emits('Hello WorldGoodnight, Moon')); completer.complete(); @@ -213,7 +212,7 @@ void main() { }); testUsingContext('executablePathForDevice uses the correct package executable', () async { - final MockMacOSApp mockApp = MockMacOSApp(); + final FakeMacOSApp package = FakeMacOSApp(); final MacOSDevice device = MacOSDevice( fileSystem: MemoryFileSystem.test(), logger: BufferLogger.test(), @@ -223,13 +222,10 @@ void main() { const String debugPath = 'debug/executable'; const String profilePath = 'profile/executable'; const String releasePath = 'release/executable'; - when(mockApp.executable(BuildMode.debug)).thenReturn(debugPath); - when(mockApp.executable(BuildMode.profile)).thenReturn(profilePath); - when(mockApp.executable(BuildMode.release)).thenReturn(releasePath); - expect(device.executablePathForDevice(mockApp, BuildMode.debug), debugPath); - expect(device.executablePathForDevice(mockApp, BuildMode.profile), profilePath); - expect(device.executablePathForDevice(mockApp, BuildMode.release), releasePath); + expect(device.executablePathForDevice(package, BuildMode.debug), debugPath); + expect(device.executablePathForDevice(package, BuildMode.profile), profilePath); + expect(device.executablePathForDevice(package, BuildMode.release), releasePath); }); } @@ -241,4 +237,18 @@ FlutterProject setUpFlutterProject(Directory directory) { return flutterProjectFactory.fromDirectory(directory); } -class MockMacOSApp extends Mock implements MacOSApp {} +class FakeMacOSApp extends Fake implements MacOSApp { + @override + String executable(BuildMode buildMode) { + switch (buildMode) { + case BuildMode.debug: + return 'debug/executable'; + case BuildMode.profile: + return 'profile/executable'; + case BuildMode.release: + return 'release/executable'; + default: + throw StateError(''); + } + } +} diff --git a/packages/flutter_tools/test/general.shard/macos/macos_project_migration_test.dart b/packages/flutter_tools/test/general.shard/macos/macos_project_migration_test.dart index 88c0439808..91130e5ddf 100644 --- a/packages/flutter_tools/test/general.shard/macos/macos_project_migration_test.dart +++ b/packages/flutter_tools/test/general.shard/macos/macos_project_migration_test.dart @@ -7,14 +7,12 @@ import 'package:file/file.dart'; import 'package:file/memory.dart'; import 'package:flutter_tools/src/base/logger.dart'; -import 'package:flutter_tools/src/base/platform.dart'; import 'package:flutter_tools/src/base/project_migrator.dart'; -import 'package:flutter_tools/src/base/terminal.dart'; import 'package:flutter_tools/src/macos/migrations/remove_macos_framework_link_and_embedding_migration.dart'; import 'package:flutter_tools/src/project.dart'; import 'package:flutter_tools/src/reporting/reporting.dart'; import 'package:meta/meta.dart'; -import 'package:mockito/mockito.dart'; +import 'package:test/fake.dart'; import '../../src/common.dart'; @@ -22,31 +20,22 @@ void main() { TestUsage testUsage; MemoryFileSystem memoryFileSystem; BufferLogger testLogger; - MockMacOSProject mockMacOSProject; + FakeMacOSProject macOSProject; File xcodeProjectInfoFile; setUp(() { testUsage = TestUsage(); memoryFileSystem = MemoryFileSystem.test(); xcodeProjectInfoFile = memoryFileSystem.file('project.pbxproj'); - - testLogger = BufferLogger( - terminal: AnsiTerminal( - stdio: null, - platform: const LocalPlatform(), - ), - outputPreferences: OutputPreferences.test(), - ); - - mockMacOSProject = MockMacOSProject(); - when(mockMacOSProject.xcodeProjectInfoFile) - .thenReturn(xcodeProjectInfoFile); + testLogger = BufferLogger.test(); + macOSProject = FakeMacOSProject(); + macOSProject.xcodeProjectInfoFile = xcodeProjectInfoFile; }); testWithoutContext('skipped if files are missing', () { final RemoveMacOSFrameworkLinkAndEmbeddingMigration macosProjectMigration = RemoveMacOSFrameworkLinkAndEmbeddingMigration( - mockMacOSProject, + macOSProject, testLogger, testUsage, ); @@ -70,7 +59,7 @@ void main() { final RemoveMacOSFrameworkLinkAndEmbeddingMigration macosProjectMigration = RemoveMacOSFrameworkLinkAndEmbeddingMigration( - mockMacOSProject, + macOSProject, testLogger, testUsage, ); @@ -91,7 +80,7 @@ shellScript = "echo \"$PRODUCT_NAME.app\" > \"$PROJECT_DIR\"/Flutter/ephemeral/. final RemoveMacOSFrameworkLinkAndEmbeddingMigration macosProjectMigration = RemoveMacOSFrameworkLinkAndEmbeddingMigration( - mockMacOSProject, + macOSProject, testLogger, testUsage, ); @@ -114,7 +103,7 @@ keep this 2 final RemoveMacOSFrameworkLinkAndEmbeddingMigration macosProjectMigration = RemoveMacOSFrameworkLinkAndEmbeddingMigration( - mockMacOSProject, + macOSProject, testLogger, testUsage, ); @@ -137,7 +126,7 @@ keep this 2 final RemoveMacOSFrameworkLinkAndEmbeddingMigration macosProjectMigration = RemoveMacOSFrameworkLinkAndEmbeddingMigration( - mockMacOSProject, + macOSProject, testLogger, testUsage, ); @@ -157,7 +146,7 @@ keep this 2 final RemoveMacOSFrameworkLinkAndEmbeddingMigration macosProjectMigration = RemoveMacOSFrameworkLinkAndEmbeddingMigration( - mockMacOSProject, + macOSProject, testLogger, testUsage, ); @@ -169,7 +158,10 @@ keep this 2 }); } -class MockMacOSProject extends Mock implements MacOSProject {} +class FakeMacOSProject extends Fake implements MacOSProject { + @override + File xcodeProjectInfoFile; +} class FakeMacOSMigrator extends ProjectMigrator { FakeMacOSMigrator({@required this.succeeds}) : super(null);