| // Copyright 2013 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 'package:flutter_migrate/src/base/common.dart'; |
| import 'package:flutter_migrate/src/base/file_system.dart'; |
| import 'package:flutter_migrate/src/base/logger.dart'; |
| import 'package:flutter_migrate/src/base/project.dart'; |
| import 'package:flutter_migrate/src/base/signals.dart'; |
| import 'package:flutter_migrate/src/compute.dart'; |
| import 'package:flutter_migrate/src/environment.dart'; |
| import 'package:flutter_migrate/src/flutter_project_metadata.dart'; |
| import 'package:flutter_migrate/src/migrate_logger.dart'; |
| import 'package:flutter_migrate/src/result.dart'; |
| import 'package:flutter_migrate/src/utils.dart'; |
| import 'package:path/path.dart'; |
| import 'package:process/process.dart'; |
| |
| import 'environment_test.dart'; |
| import 'src/common.dart'; |
| import 'src/context.dart'; |
| import 'src/test_utils.dart'; |
| import 'test_data/migrate_project.dart'; |
| |
| void main() { |
| late FileSystem fileSystem; |
| late BufferLogger logger; |
| late MigrateUtils utils; |
| late MigrateContext context; |
| late MigrateResult result; |
| late Directory targetFlutterDirectory; |
| late Directory newerTargetFlutterDirectory; |
| late Directory currentDir; |
| late FlutterToolsEnvironment environment; |
| late ProcessManager processManager; |
| late FakeProcessManager envProcessManager; |
| late String separator; |
| |
| const String oldSdkRevision = '5391447fae6209bb21a89e6a5a6583cac1af9b4b'; |
| const String newSdkRevision = '85684f9300908116a78138ea4c6036c35c9a1236'; |
| |
| Future<void> setUpFullEnv() async { |
| fileSystem = LocalFileSystem.test(signals: LocalSignals.instance); |
| currentDir = createResolvedTempDirectorySync('current_app.'); |
| logger = BufferLogger.test(); |
| processManager = const LocalProcessManager(); |
| utils = MigrateUtils( |
| logger: logger, |
| fileSystem: fileSystem, |
| processManager: processManager, |
| ); |
| await MigrateProject.installProject('version:1.22.6_stable', currentDir); |
| final FlutterProjectFactory flutterFactory = FlutterProjectFactory(); |
| final FlutterProject flutterProject = |
| flutterFactory.fromDirectory(currentDir); |
| result = MigrateResult.empty(); |
| final MigrateLogger migrateLogger = |
| MigrateLogger(logger: logger, verbose: true); |
| migrateLogger.start(); |
| separator = isWindows ? r'\\' : '/'; |
| envProcessManager = FakeProcessManager(''' |
| { |
| "FlutterProject.directory": "/Users/test/flutter", |
| "FlutterProject.metadataFile": "/Users/test/flutter/.metadata", |
| "FlutterProject.android.exists": false, |
| "FlutterProject.ios.exists": false, |
| "FlutterProject.web.exists": false, |
| "FlutterProject.macos.exists": false, |
| "FlutterProject.linux.exists": false, |
| "FlutterProject.windows.exists": false, |
| "FlutterProject.fuchsia.exists": false, |
| "FlutterProject.android.isKotlin": false, |
| "FlutterProject.ios.isSwift": false, |
| "FlutterProject.isModule": false, |
| "FlutterProject.isPlugin": false, |
| "FlutterProject.manifest.appname": "test_app_name", |
| "FlutterVersion.frameworkRevision": "4e181f012c717777681862e4771af5a941774bb9", |
| "Platform.operatingSystem": "macos", |
| "Platform.isAndroid": true, |
| "Platform.isIOS": false, |
| "Platform.isWindows": ${isWindows ? 'true' : 'false'}, |
| "Platform.isMacOS": ${isMacOS ? 'true' : 'false'}, |
| "Platform.isFuchsia": false, |
| "Platform.pathSeparator": "$separator", |
| "Cache.flutterRoot": "/Users/test/flutter" |
| } |
| '''); |
| environment = |
| await FlutterToolsEnvironment.initializeFlutterToolsEnvironment( |
| envProcessManager, logger); |
| context = MigrateContext( |
| flutterProject: flutterProject, |
| skippedPrefixes: <String>{}, |
| fileSystem: fileSystem, |
| migrateLogger: migrateLogger, |
| migrateUtils: utils, |
| environment: environment, |
| ); |
| targetFlutterDirectory = |
| createResolvedTempDirectorySync('targetFlutterDir.'); |
| newerTargetFlutterDirectory = |
| createResolvedTempDirectorySync('newerTargetFlutterDir.'); |
| await context.migrateUtils |
| .cloneFlutter(oldSdkRevision, targetFlutterDirectory.absolute.path); |
| await context.migrateUtils.cloneFlutter( |
| newSdkRevision, newerTargetFlutterDirectory.absolute.path); |
| } |
| |
| group('MigrateFlutterProject', () { |
| setUp(() async { |
| await setUpFullEnv(); |
| }); |
| |
| tearDown(() async { |
| tryToDelete(targetFlutterDirectory); |
| tryToDelete(newerTargetFlutterDirectory); |
| }); |
| |
| testUsingContext('MigrateTargetFlutterProject creates', () async { |
| final Directory workingDir = |
| createResolvedTempDirectorySync('migrate_working_dir.'); |
| final Directory targetDir = |
| createResolvedTempDirectorySync('target_dir.'); |
| result.generatedTargetTemplateDirectory = targetDir; |
| workingDir.createSync(recursive: true); |
| final MigrateTargetFlutterProject targetProject = |
| MigrateTargetFlutterProject( |
| path: null, |
| directory: targetDir, |
| name: 'base', |
| androidLanguage: 'java', |
| iosLanguage: 'objc', |
| ); |
| |
| await targetProject.createProject( |
| context, |
| result, |
| oldSdkRevision, //targetRevision |
| targetFlutterDirectory, //targetFlutterDirectory |
| ); |
| |
| expect(targetDir.childFile('pubspec.yaml').existsSync(), true); |
| expect( |
| targetDir |
| .childDirectory('android') |
| .childFile('build.gradle') |
| .existsSync(), |
| true); |
| }, timeout: const Timeout(Duration(seconds: 500))); |
| |
| testUsingContext('MigrateBaseFlutterProject creates', () async { |
| final Directory workingDir = |
| createResolvedTempDirectorySync('migrate_working_dir.'); |
| final Directory baseDir = createResolvedTempDirectorySync('base_dir.'); |
| result.generatedBaseTemplateDirectory = baseDir; |
| workingDir.createSync(recursive: true); |
| final MigrateBaseFlutterProject baseProject = MigrateBaseFlutterProject( |
| path: null, |
| directory: baseDir, |
| name: 'base', |
| androidLanguage: 'java', |
| iosLanguage: 'objc', |
| ); |
| |
| await baseProject.createProject( |
| context, |
| result, |
| <String>[oldSdkRevision], //revisionsList |
| <String, List<MigratePlatformConfig>>{ |
| oldSdkRevision: <MigratePlatformConfig>[ |
| MigratePlatformConfig(component: FlutterProjectComponent.android), |
| MigratePlatformConfig(component: FlutterProjectComponent.ios) |
| ], |
| }, //revisionToConfigs |
| oldSdkRevision, //fallbackRevision |
| oldSdkRevision, //targetRevision |
| targetFlutterDirectory, //targetFlutterDirectory |
| ); |
| |
| expect(baseDir.childFile('pubspec.yaml').existsSync(), true); |
| expect( |
| baseDir |
| .childDirectory('android') |
| .childFile('build.gradle') |
| .existsSync(), |
| true); |
| }, timeout: const Timeout(Duration(seconds: 500))); |
| |
| testUsingContext('Migrate___FlutterProject skips when path exists', |
| () async { |
| final Directory workingDir = |
| createResolvedTempDirectorySync('migrate_working_dir.'); |
| final Directory targetDir = |
| createResolvedTempDirectorySync('target_dir.'); |
| final Directory baseDir = createResolvedTempDirectorySync('base_dir.'); |
| result.generatedTargetTemplateDirectory = targetDir; |
| result.generatedBaseTemplateDirectory = baseDir; |
| workingDir.createSync(recursive: true); |
| |
| final MigrateBaseFlutterProject baseProject = MigrateBaseFlutterProject( |
| path: 'some_existing_base_path', |
| directory: baseDir, |
| name: 'base', |
| androidLanguage: 'java', |
| iosLanguage: 'objc', |
| ); |
| final MigrateTargetFlutterProject targetProject = |
| MigrateTargetFlutterProject( |
| path: 'some_existing_target_path', |
| directory: targetDir, |
| name: 'base', |
| androidLanguage: 'java', |
| iosLanguage: 'objc', |
| ); |
| |
| await baseProject.createProject( |
| context, |
| result, |
| <String>[oldSdkRevision], //revisionsList |
| <String, List<MigratePlatformConfig>>{ |
| oldSdkRevision: <MigratePlatformConfig>[ |
| MigratePlatformConfig(component: FlutterProjectComponent.android), |
| MigratePlatformConfig(component: FlutterProjectComponent.ios) |
| ], |
| }, //revisionToConfigs |
| oldSdkRevision, //fallbackRevision |
| oldSdkRevision, //targetRevision |
| targetFlutterDirectory, //targetFlutterDirectory |
| ); |
| |
| expect(baseDir.childFile('pubspec.yaml').existsSync(), false); |
| expect( |
| baseDir |
| .childDirectory('android') |
| .childFile('build.gradle') |
| .existsSync(), |
| false); |
| |
| await targetProject.createProject( |
| context, |
| result, |
| oldSdkRevision, //revisionsList |
| targetFlutterDirectory, //targetFlutterDirectory |
| ); |
| |
| expect(targetDir.childFile('pubspec.yaml').existsSync(), false); |
| expect( |
| targetDir |
| .childDirectory('android') |
| .childFile('build.gradle') |
| .existsSync(), |
| false); |
| }, timeout: const Timeout(Duration(seconds: 500))); |
| }, |
| // TODO(stuartmorgan): These should not be unit tests, see |
| // https://github.com/flutter/flutter/issues/121257. |
| skip: 'TODO: Speed up, or move to another type of test'); |
| |
| group('MigrateRevisions', () { |
| setUp(() async { |
| fileSystem = LocalFileSystem.test(signals: LocalSignals.instance); |
| currentDir = createResolvedTempDirectorySync('current_app.'); |
| logger = BufferLogger.test(); |
| utils = MigrateUtils( |
| logger: logger, |
| fileSystem: fileSystem, |
| processManager: const LocalProcessManager(), |
| ); |
| await MigrateProject.installProject('version:1.22.6_stable', currentDir); |
| final FlutterProjectFactory flutterFactory = FlutterProjectFactory(); |
| final FlutterProject flutterProject = |
| flutterFactory.fromDirectory(currentDir); |
| result = MigrateResult.empty(); |
| final MigrateLogger migrateLogger = |
| MigrateLogger(logger: logger, verbose: true); |
| migrateLogger.start(); |
| context = MigrateContext( |
| flutterProject: flutterProject, |
| skippedPrefixes: <String>{}, |
| fileSystem: fileSystem, |
| migrateLogger: migrateLogger, |
| migrateUtils: utils, |
| environment: environment, |
| ); |
| }); |
| |
| testUsingContext('extracts revisions underpopulated metadata', () async { |
| final MigrateRevisions revisions = MigrateRevisions( |
| context: context, |
| baseRevision: oldSdkRevision, |
| allowFallbackBaseRevision: true, |
| platforms: <SupportedPlatform>[ |
| SupportedPlatform.android, |
| SupportedPlatform.ios |
| ], |
| environment: environment, |
| ); |
| |
| expect(revisions.revisionsList, <String>[oldSdkRevision]); |
| expect(revisions.fallbackRevision, oldSdkRevision); |
| expect(revisions.metadataRevision, |
| '9b2d32b605630f28625709ebd9d78ab3016b2bf6'); |
| expect(revisions.config.unmanagedFiles.isEmpty, false); |
| expect(revisions.config.platformConfigs.isEmpty, false); |
| expect(revisions.config.platformConfigs.length, 3); |
| expect( |
| revisions.config.platformConfigs |
| .containsKey(FlutterProjectComponent.root), |
| true); |
| expect( |
| revisions.config.platformConfigs |
| .containsKey(FlutterProjectComponent.android), |
| true); |
| expect( |
| revisions.config.platformConfigs |
| .containsKey(FlutterProjectComponent.ios), |
| true); |
| }); |
| |
| testUsingContext('extracts revisions full metadata', () async { |
| final File metadataFile = |
| context.flutterProject.directory.childFile('.metadata'); |
| if (metadataFile.existsSync()) { |
| if (!tryToDelete(metadataFile)) { |
| // TODO(garyq): Inaccessible .metadata on windows. |
| // Skip test for now. We should reneable. |
| return; |
| } |
| } |
| metadataFile.createSync(recursive: true); |
| metadataFile.writeAsStringSync(''' |
| # This file tracks properties of this Flutter project. |
| # Used by Flutter tool to assess capabilities and perform upgrades etc. |
| # |
| # This file should be version controlled and should not be manually edited. |
| |
| version: |
| revision: 9b2d32b605630f28625709ebd9d78ab3016b2bf6 |
| channel: unknown |
| |
| project_type: app |
| |
| # Tracks metadata for the flutter migrate command |
| migration: |
| platforms: |
| - platform: root |
| create_revision: 9b2d32b605630f28625709ebd9d78ab3016b2bf6 |
| base_revision: 9b2d32b605630f28625709ebd9d78ab3016b2bf6 |
| - platform: android |
| create_revision: 9b2d32b605630f28625709ebd9d78ab3016b2bf6 |
| base_revision: 9b2d32b605630f28625709ebd9d78ab3016b2bf6 |
| - platform: ios |
| create_revision: 9b2d32b605630f28625709ebd9d78ab3016b2bf6 |
| base_revision: 9b2d32b605630f28625709ebd9d78ab3016b2bf6 |
| - platform: linux |
| create_revision: 9b2d32b605630f28625709ebd9d78ab3016b2bf6 |
| base_revision: 9b2d32b605630f28625709ebd9d78ab3016b2bf6 |
| - platform: macos |
| create_revision: 9b2d32b605630f28625709ebd9d78ab3016b2bf6 |
| base_revision: 9b2d32b605630f28625709ebd9d78ab3016b2bf6 |
| - platform: web |
| create_revision: 9b2d32b605630f28625709ebd9d78ab3016b2bf6 |
| base_revision: 9b2d32b605630f28625709ebd9d78ab3016b2bf6 |
| - platform: windows |
| create_revision: 36427af29421f406ac95ff55ea31d1dc49a45b5f |
| base_revision: 36427af29421f406ac95ff55ea31d1dc49a45b5f |
| |
| # User provided section |
| |
| # List of Local paths (relative to this file) that should be |
| # ignored by the migrate tool. |
| # |
| # Files that are not part of the templates will be ignored by default. |
| unmanaged_files: |
| - 'lib/main.dart' |
| - 'blah.dart' |
| - 'ios/Runner.xcodeproj/project.pbxproj' |
| ''', flush: true); |
| |
| final MigrateRevisions revisions = MigrateRevisions( |
| context: context, |
| baseRevision: oldSdkRevision, |
| allowFallbackBaseRevision: true, |
| platforms: <SupportedPlatform>[ |
| SupportedPlatform.android, |
| SupportedPlatform.ios |
| ], |
| environment: environment, |
| ); |
| |
| expect(revisions.revisionsList, <String>[oldSdkRevision]); |
| expect(revisions.fallbackRevision, oldSdkRevision); |
| expect(revisions.metadataRevision, |
| '9b2d32b605630f28625709ebd9d78ab3016b2bf6'); |
| expect(revisions.config.unmanagedFiles.isEmpty, false); |
| expect(revisions.config.unmanagedFiles.length, 3); |
| expect(revisions.config.unmanagedFiles.contains('lib/main.dart'), true); |
| expect(revisions.config.unmanagedFiles.contains('blah.dart'), true); |
| expect( |
| revisions.config.unmanagedFiles |
| .contains('ios/Runner.xcodeproj/project.pbxproj'), |
| true); |
| |
| expect(revisions.config.platformConfigs.length, 7); |
| expect( |
| revisions.config.platformConfigs |
| .containsKey(FlutterProjectComponent.root), |
| true); |
| expect( |
| revisions.config.platformConfigs |
| .containsKey(FlutterProjectComponent.android), |
| true); |
| expect( |
| revisions.config.platformConfigs |
| .containsKey(FlutterProjectComponent.ios), |
| true); |
| expect( |
| revisions.config.platformConfigs |
| .containsKey(FlutterProjectComponent.linux), |
| true); |
| expect( |
| revisions.config.platformConfigs |
| .containsKey(FlutterProjectComponent.macos), |
| true); |
| expect( |
| revisions.config.platformConfigs |
| .containsKey(FlutterProjectComponent.web), |
| true); |
| expect( |
| revisions.config.platformConfigs |
| .containsKey(FlutterProjectComponent.windows), |
| true); |
| |
| expect( |
| revisions.config.platformConfigs[FlutterProjectComponent.root]! |
| .createRevision, |
| '9b2d32b605630f28625709ebd9d78ab3016b2bf6'); |
| expect( |
| revisions.config.platformConfigs[FlutterProjectComponent.android]! |
| .createRevision, |
| '9b2d32b605630f28625709ebd9d78ab3016b2bf6'); |
| expect( |
| revisions.config.platformConfigs[FlutterProjectComponent.ios]! |
| .createRevision, |
| '9b2d32b605630f28625709ebd9d78ab3016b2bf6'); |
| expect( |
| revisions.config.platformConfigs[FlutterProjectComponent.linux]! |
| .createRevision, |
| '9b2d32b605630f28625709ebd9d78ab3016b2bf6'); |
| expect( |
| revisions.config.platformConfigs[FlutterProjectComponent.macos]! |
| .createRevision, |
| '9b2d32b605630f28625709ebd9d78ab3016b2bf6'); |
| expect( |
| revisions.config.platformConfigs[FlutterProjectComponent.web]! |
| .createRevision, |
| '9b2d32b605630f28625709ebd9d78ab3016b2bf6'); |
| expect( |
| revisions.config.platformConfigs[FlutterProjectComponent.windows]! |
| .createRevision, |
| '36427af29421f406ac95ff55ea31d1dc49a45b5f'); |
| |
| expect( |
| revisions.config.platformConfigs[FlutterProjectComponent.root]! |
| .baseRevision, |
| '9b2d32b605630f28625709ebd9d78ab3016b2bf6'); |
| expect( |
| revisions.config.platformConfigs[FlutterProjectComponent.android]! |
| .baseRevision, |
| '9b2d32b605630f28625709ebd9d78ab3016b2bf6'); |
| expect( |
| revisions.config.platformConfigs[FlutterProjectComponent.ios]! |
| .baseRevision, |
| '9b2d32b605630f28625709ebd9d78ab3016b2bf6'); |
| expect( |
| revisions.config.platformConfigs[FlutterProjectComponent.linux]! |
| .baseRevision, |
| '9b2d32b605630f28625709ebd9d78ab3016b2bf6'); |
| expect( |
| revisions.config.platformConfigs[FlutterProjectComponent.macos]! |
| .baseRevision, |
| '9b2d32b605630f28625709ebd9d78ab3016b2bf6'); |
| expect( |
| revisions.config.platformConfigs[FlutterProjectComponent.web]! |
| .baseRevision, |
| '9b2d32b605630f28625709ebd9d78ab3016b2bf6'); |
| expect( |
| revisions.config.platformConfigs[FlutterProjectComponent.windows]! |
| .baseRevision, |
| '36427af29421f406ac95ff55ea31d1dc49a45b5f'); |
| }); |
| }, |
| // TODO(stuartmorgan): These should not be unit tests, see |
| // https://github.com/flutter/flutter/issues/121257. |
| skip: 'TODO: Speed up, or move to another type of test'); |
| |
| group('project operations', () { |
| setUp(() async { |
| await setUpFullEnv(); |
| }); |
| |
| tearDown(() async { |
| tryToDelete(targetFlutterDirectory); |
| tryToDelete(newerTargetFlutterDirectory); |
| }); |
| |
| testUsingContext('diff base and target', () async { |
| final Directory workingDir = |
| createResolvedTempDirectorySync('migrate_working_dir.'); |
| final Directory targetDir = |
| createResolvedTempDirectorySync('target_dir.'); |
| final Directory baseDir = createResolvedTempDirectorySync('base_dir.'); |
| result.generatedTargetTemplateDirectory = targetDir; |
| result.generatedBaseTemplateDirectory = baseDir; |
| workingDir.createSync(recursive: true); |
| |
| final MigrateBaseFlutterProject baseProject = MigrateBaseFlutterProject( |
| path: null, |
| directory: baseDir, |
| name: 'base', |
| androidLanguage: 'java', |
| iosLanguage: 'objc', |
| ); |
| final MigrateTargetFlutterProject targetProject = |
| MigrateTargetFlutterProject( |
| path: null, |
| directory: targetDir, |
| name: 'base', |
| androidLanguage: 'java', |
| iosLanguage: 'objc', |
| ); |
| |
| await baseProject.createProject( |
| context, |
| result, |
| <String>[oldSdkRevision], //revisionsList |
| <String, List<MigratePlatformConfig>>{ |
| oldSdkRevision: <MigratePlatformConfig>[ |
| MigratePlatformConfig(component: FlutterProjectComponent.android), |
| MigratePlatformConfig(component: FlutterProjectComponent.ios) |
| ], |
| }, //revisionToConfigs |
| oldSdkRevision, //fallbackRevision |
| oldSdkRevision, //targetRevision |
| targetFlutterDirectory, //targetFlutterDirectory |
| ); |
| |
| expect(baseDir.childFile('pubspec.yaml').existsSync(), true); |
| expect( |
| baseDir |
| .childDirectory('android') |
| .childFile('build.gradle') |
| .existsSync(), |
| true); |
| |
| await targetProject.createProject( |
| context, |
| result, |
| newSdkRevision, //revisionsList |
| newerTargetFlutterDirectory, //targetFlutterDirectory |
| ); |
| |
| expect(targetDir.childFile('pubspec.yaml').existsSync(), true); |
| expect( |
| targetDir |
| .childDirectory('android') |
| .childFile('build.gradle') |
| .existsSync(), |
| true); |
| |
| final Map<String, DiffResult> diffResults = |
| await baseProject.diff(context, targetProject); |
| final Map<String, DiffResult> canonicalizedDiffResults = |
| <String, DiffResult>{}; |
| for (final MapEntry<String, DiffResult> entry in diffResults.entries) { |
| canonicalizedDiffResults[canonicalize(entry.key)] = entry.value; |
| } |
| result.diffMap.addAll(diffResults); |
| |
| List<String> expectedFiles = <String>[ |
| '.metadata', |
| 'ios/Runner.xcworkspace/contents.xcworkspacedata', |
| 'ios/Runner/AppDelegate.h', |
| 'ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png', |
| 'ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png', |
| 'ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md', |
| 'ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json', |
| 'ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png', |
| 'ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png', |
| 'ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png', |
| 'ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png', |
| 'ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png', |
| 'ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png', |
| 'ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png', |
| 'ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png', |
| 'ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json', |
| 'ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png', |
| 'ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png', |
| 'ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png', |
| 'ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png', |
| 'ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png', |
| 'ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png', |
| 'ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png', |
| 'ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png', |
| 'ios/Runner/Base.lproj/LaunchScreen.storyboard', |
| 'ios/Runner/Base.lproj/Main.storyboard', |
| 'ios/Runner/main.m', |
| 'ios/Runner/AppDelegate.m', |
| 'ios/Runner/Info.plist', |
| 'ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata', |
| 'ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme', |
| 'ios/Flutter/Debug.xcconfig', |
| 'ios/Flutter/Release.xcconfig', |
| 'ios/Flutter/AppFrameworkInfo.plist', |
| 'pubspec.yaml', |
| '.gitignore', |
| 'android/base_android.iml', |
| 'android/app/build.gradle', |
| 'android/app/src/main/res/mipmap-mdpi/ic_launcher.png', |
| 'android/app/src/main/res/mipmap-hdpi/ic_launcher.png', |
| 'android/app/src/main/res/drawable/launch_background.xml', |
| 'android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png', |
| 'android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png', |
| 'android/app/src/main/res/values/styles.xml', |
| 'android/app/src/main/res/mipmap-xhdpi/ic_launcher.png', |
| 'android/app/src/main/AndroidManifest.xml', |
| 'android/app/src/main/java/com/example/base/MainActivity.java', |
| 'android/local.properties', |
| 'android/gradle/wrapper/gradle-wrapper.jar', |
| 'android/gradle/wrapper/gradle-wrapper.properties', |
| 'android/gradlew', |
| 'android/build.gradle', |
| 'android/gradle.properties', |
| 'android/gradlew.bat', |
| 'android/settings.gradle', |
| 'base.iml', |
| '.idea/runConfigurations/main_dart.xml', |
| '.idea/libraries/Dart_SDK.xml', |
| '.idea/libraries/KotlinJavaRuntime.xml', |
| '.idea/libraries/Flutter_for_Android.xml', |
| '.idea/workspace.xml', |
| '.idea/modules.xml', |
| ]; |
| expectedFiles = |
| List<String>.from(expectedFiles.map((String e) => canonicalize(e))); |
| expect(diffResults.length, 62); |
| expect(expectedFiles.length, 62); |
| for (final String diffResultPath in canonicalizedDiffResults.keys) { |
| expect(expectedFiles.contains(diffResultPath), true); |
| } |
| // Spot check diffs on key files: |
| expect( |
| canonicalizedDiffResults[canonicalize('android/build.gradle')]!.diff, |
| contains(r''' |
| @@ -1,18 +1,20 @@ |
| buildscript { |
| + ext.kotlin_version = '1.6.10' |
| repositories { |
| google() |
| - jcenter() |
| + mavenCentral() |
| }''')); |
| expect( |
| canonicalizedDiffResults[canonicalize('android/build.gradle')]!.diff, |
| contains(r''' |
| dependencies { |
| - classpath 'com.android.tools.build:gradle:3.2.1' |
| + classpath 'com.android.tools.build:gradle:7.1.2' |
| + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" |
| } |
| }''')); |
| expect( |
| canonicalizedDiffResults[canonicalize('android/build.gradle')]!.diff, |
| contains(r''' |
| allprojects { |
| repositories { |
| google() |
| - jcenter() |
| + mavenCentral() |
| } |
| }''')); |
| expect( |
| canonicalizedDiffResults[ |
| canonicalize('android/app/src/main/AndroidManifest.xml')]! |
| .diff, |
| contains(r''' |
| @@ -1,39 +1,34 @@ |
| <manifest xmlns:android="http://schemas.android.com/apk/res/android" |
| package="com.example.base"> |
| - |
| - <!-- The INTERNET permission is required for development. Specifically, |
| - flutter needs it to communicate with the running application |
| - to allow setting breakpoints, to provide hot reload, etc. |
| - --> |
| - <uses-permission android:name="android.permission.INTERNET"/> |
| - |
| - <!-- io.flutter.app.FlutterApplication is an android.app.Application that |
| - calls FlutterMain.startInitialization(this); in its onCreate method. |
| - In most cases you can leave this as-is, but you if you want to provide |
| - additional functionality it is fine to subclass or reimplement |
| - FlutterApplication and put your custom class here. --> |
| - <application |
| - android:name="io.flutter.app.FlutterApplication" |
| + <application |
| android:label="base" |
| + android:name="${applicationName}" |
| android:icon="@mipmap/ic_launcher"> |
| <activity |
| android:name=".MainActivity" |
| + android:exported="true" |
| android:launchMode="singleTop" |
| android:theme="@style/LaunchTheme" |
| - android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density" |
| + android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode" |
| android:hardwareAccelerated="true" |
| android:windowSoftInputMode="adjustResize"> |
| - <!-- This keeps the window background of the activity showing |
| - until Flutter renders its first frame. It can be removed if |
| - there is no splash screen (such as the default splash screen |
| - defined in @style/LaunchTheme). --> |
| + <!-- Specifies an Android theme to apply to this Activity as soon as |
| + the Android process has started. This theme is visible to the user |
| + while the Flutter UI initializes. After that, this theme continues |
| + to determine the Window background behind the Flutter UI. --> |
| <meta-data |
| - android:name="io.flutter.app.android.SplashScreenUntilFirstFrame" |
| - android:value="true" /> |
| + android:name="io.flutter.embedding.android.NormalTheme" |
| + android:resource="@style/NormalTheme" |
| + /> |
| <intent-filter> |
| <action android:name="android.intent.action.MAIN"/> |
| <category android:name="android.intent.category.LAUNCHER"/> |
| </intent-filter> |
| </activity> |
| + <!-- Don't delete the meta-data below. |
| + This is used by the Flutter tool to generate GeneratedPluginRegistrant.java --> |
| + <meta-data |
| + android:name="flutterEmbedding" |
| + android:value="2" /> |
| </application> |
| </manifest>''')); |
| }, timeout: const Timeout(Duration(seconds: 500))); |
| |
| testUsingContext('Merge succeeds', () async { |
| final Directory workingDir = |
| createResolvedTempDirectorySync('migrate_working_dir.'); |
| final Directory targetDir = |
| createResolvedTempDirectorySync('target_dir.'); |
| final Directory baseDir = createResolvedTempDirectorySync('base_dir.'); |
| result.generatedTargetTemplateDirectory = targetDir; |
| result.generatedBaseTemplateDirectory = baseDir; |
| workingDir.createSync(recursive: true); |
| |
| final MigrateBaseFlutterProject baseProject = MigrateBaseFlutterProject( |
| path: null, |
| directory: baseDir, |
| name: 'base', |
| androidLanguage: 'java', |
| iosLanguage: 'objc', |
| ); |
| final MigrateTargetFlutterProject targetProject = |
| MigrateTargetFlutterProject( |
| path: null, |
| directory: targetDir, |
| name: 'base', |
| androidLanguage: 'java', |
| iosLanguage: 'objc', |
| ); |
| |
| await baseProject.createProject( |
| context, |
| result, |
| <String>[oldSdkRevision], //revisionsList |
| <String, List<MigratePlatformConfig>>{ |
| oldSdkRevision: <MigratePlatformConfig>[ |
| MigratePlatformConfig(component: FlutterProjectComponent.android), |
| MigratePlatformConfig(component: FlutterProjectComponent.ios) |
| ], |
| }, //revisionToConfigs |
| oldSdkRevision, //fallbackRevision |
| oldSdkRevision, //targetRevision |
| targetFlutterDirectory, //targetFlutterDirectory |
| ); |
| |
| expect(baseDir.childFile('pubspec.yaml').existsSync(), true); |
| expect(baseDir.childFile('.metadata').existsSync(), true); |
| expect( |
| baseDir |
| .childDirectory('android') |
| .childFile('build.gradle') |
| .existsSync(), |
| true); |
| |
| await targetProject.createProject( |
| context, |
| result, |
| newSdkRevision, //revisionsList |
| newerTargetFlutterDirectory, //targetFlutterDirectory |
| ); |
| |
| expect(targetDir.childFile('pubspec.yaml').existsSync(), true); |
| expect(targetDir.childFile('.metadata').existsSync(), true); |
| expect( |
| targetDir |
| .childDirectory('android') |
| .childFile('build.gradle') |
| .existsSync(), |
| true); |
| |
| result.diffMap.addAll(await baseProject.diff(context, targetProject)); |
| |
| await MigrateFlutterProject.merge( |
| context, |
| result, |
| baseProject, |
| targetProject, |
| <String>[], // unmanagedFiles |
| <String>[], // unmanagedDirectories |
| false, // preferTwoWayMerge |
| ); |
| |
| List<String> expectedMergedPaths = <String>[ |
| '.metadata', |
| 'ios/Runner/Info.plist', |
| 'ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata', |
| 'ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme', |
| 'ios/Flutter/AppFrameworkInfo.plist', |
| 'pubspec.yaml', |
| '.gitignore', |
| 'android/app/build.gradle', |
| 'android/app/src/main/res/values/styles.xml', |
| 'android/app/src/main/AndroidManifest.xml', |
| 'android/gradle/wrapper/gradle-wrapper.properties', |
| 'android/build.gradle', |
| ]; |
| expectedMergedPaths = List<String>.from( |
| expectedMergedPaths.map((String e) => canonicalize(e))); |
| expect(result.mergeResults.length, 12); |
| expect(expectedMergedPaths.length, 12); |
| |
| for (final MergeResult mergeResult in result.mergeResults) { |
| expect( |
| expectedMergedPaths.contains(canonicalize(mergeResult.localPath)), |
| true); |
| } |
| |
| expect(result.mergeResults[0].exitCode, 0); |
| expect(result.mergeResults[1].exitCode, 0); |
| expect(result.mergeResults[2].exitCode, 0); |
| expect(result.mergeResults[3].exitCode, 0); |
| expect(result.mergeResults[4].exitCode, 0); |
| expect(result.mergeResults[5].exitCode, 0); |
| expect(result.mergeResults[6].exitCode, 0); |
| expect(result.mergeResults[7].exitCode, 0); |
| expect(result.mergeResults[8].exitCode, 0); |
| expect(result.mergeResults[9].exitCode, 0); |
| expect(result.mergeResults[10].exitCode, 0); |
| expect(result.mergeResults[11].exitCode, 0); |
| |
| expect(result.mergeResults[0].hasConflict, false); |
| expect(result.mergeResults[1].hasConflict, false); |
| expect(result.mergeResults[2].hasConflict, false); |
| expect(result.mergeResults[3].hasConflict, false); |
| expect(result.mergeResults[4].hasConflict, false); |
| expect(result.mergeResults[5].hasConflict, false); |
| expect(result.mergeResults[6].hasConflict, false); |
| expect(result.mergeResults[7].hasConflict, false); |
| expect(result.mergeResults[8].hasConflict, false); |
| expect(result.mergeResults[9].hasConflict, false); |
| expect(result.mergeResults[10].hasConflict, false); |
| expect(result.mergeResults[11].hasConflict, false); |
| }, timeout: const Timeout(Duration(seconds: 500))); |
| }, |
| // TODO(stuartmorgan): These should not be unit tests, see |
| // https://github.com/flutter/flutter/issues/121257. |
| skip: 'TODO: Speed up, or move to another type of test'); |
| } |