From 76784651d42a42399cf2a24d92a2afe3b9a2cf89 Mon Sep 17 00:00:00 2001 From: Dan Field Date: Thu, 5 Nov 2020 17:28:47 -0800 Subject: [PATCH] Move package:integration_test to flutter/flutter (#69622) --- dev/automated_tests/pubspec.yaml | 4 +- dev/benchmarks/complex_layout/pubspec.yaml | 4 +- dev/benchmarks/macrobenchmarks/pubspec.yaml | 7 +- dev/benchmarks/microbenchmarks/pubspec.yaml | 4 +- .../platform_views_layout/pubspec.yaml | 4 +- .../pubspec.yaml | 4 +- dev/benchmarks/test_apps/stocks/pubspec.yaml | 4 +- dev/bots/analyze.dart | 1 + dev/bots/pubspec.yaml | 4 +- dev/bots/test.dart | 1 + dev/devicelab/pubspec.yaml | 4 +- .../android_semantics_testing/pubspec.yaml | 4 +- .../splash_screen_kitchen_sink/pubspec.yaml | 4 +- .../splash_screen_trans_rotate/pubspec.yaml | 4 +- .../android_views/pubspec.yaml | 4 +- dev/integration_tests/channels/pubspec.yaml | 4 +- .../external_ui/pubspec.yaml | 4 +- dev/integration_tests/flavors/pubspec.yaml | 4 +- .../pubspec.yaml | 4 +- .../flutter_gallery/pubspec.yaml | 7 +- .../hybrid_android_views/pubspec.yaml | 4 +- .../image_loading/pubspec.yaml | 4 +- .../ios_platform_view_tests/pubspec.yaml | 4 +- .../platform_interaction/pubspec.yaml | 4 +- dev/integration_tests/ui/pubspec.yaml | 4 +- .../web_e2e_tests/pubspec.yaml | 7 +- dev/snippets/pubspec.yaml | 4 +- dev/tools/pubspec.yaml | 4 +- examples/hello_world/pubspec.yaml | 4 +- examples/platform_channel/pubspec.yaml | 4 +- examples/platform_channel_swift/pubspec.yaml | 4 +- .../_flutter_web_build_script/pubspec.yaml | 4 +- packages/flutter_driver/pubspec.yaml | 4 +- .../lib/src/commands/update_packages.dart | 4 +- packages/flutter_tools/pubspec.yaml | 4 +- .../pubspec.yaml | 4 +- packages/integration_test/CHANGELOG.md | 228 ++++++ packages/integration_test/README.md | 212 +++++ packages/integration_test/android/.gitignore | 8 + .../integration_test/android/build.gradle | 48 ++ .../android/gradle.properties | 1 + .../integration_test/android/settings.gradle | 5 + .../android/src/main/AndroidManifest.xml | 7 + .../integration_test/FlutterTestRunner.java | 87 +++ .../IntegrationTestPlugin.java | 61 ++ packages/integration_test/example/.gitignore | 73 ++ packages/integration_test/example/README.md | 22 + .../example/android/app/build.gradle | 65 ++ .../e2e_example/EmbedderV1ActivityTest.java | 17 + .../e2e_example/FlutterActivityTest.java | 18 + .../FlutterActivityWithPermissionTest.java | 30 + .../android/app/src/debug/AndroidManifest.xml | 11 + .../android/app/src/main/AndroidManifest.xml | 36 + .../e2e_example/EmbedderV1Activity.java | 18 + .../main/res/drawable/launch_background.xml | 16 + .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 544 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 442 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 721 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 1031 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 1443 bytes .../app/src/main/res/values/styles.xml | 12 + .../app/src/profile/AndroidManifest.xml | 11 + .../example/android/build.gradle | 33 + .../example/android/gradle.properties | 4 + .../gradle/wrapper/gradle-wrapper.properties | 6 + .../example/android/settings.gradle | 19 + .../integration_test/_example_test_io.dart | 45 ++ .../integration_test/_example_test_web.dart | 39 + .../integration_test/_extended_test_io.dart | 42 + .../integration_test/_extended_test_web.dart | 55 ++ .../integration_test/example_test.dart | 20 + .../integration_test/extended_test.dart | 23 + .../ios/Flutter/AppFrameworkInfo.plist | 26 + .../example/ios/Flutter/Debug.xcconfig | 2 + .../example/ios/Flutter/Release.xcconfig | 2 + packages/integration_test/example/ios/Podfile | 38 + .../ios/Runner.xcodeproj/project.pbxproj | 733 ++++++++++++++++++ .../xcshareddata/xcschemes/Runner.xcscheme | 97 +++ .../example/ios/Runner/AppDelegate.h | 10 + .../example/ios/Runner/AppDelegate.m | 17 + .../AppIcon.appiconset/Contents.json | 122 +++ .../Icon-App-1024x1024@1x.png | Bin 0 -> 10932 bytes .../AppIcon.appiconset/Icon-App-20x20@1x.png | Bin 0 -> 564 bytes .../AppIcon.appiconset/Icon-App-20x20@2x.png | Bin 0 -> 1283 bytes .../AppIcon.appiconset/Icon-App-20x20@3x.png | Bin 0 -> 1588 bytes .../AppIcon.appiconset/Icon-App-29x29@1x.png | Bin 0 -> 1025 bytes .../AppIcon.appiconset/Icon-App-29x29@2x.png | Bin 0 -> 1716 bytes .../AppIcon.appiconset/Icon-App-29x29@3x.png | Bin 0 -> 1920 bytes .../AppIcon.appiconset/Icon-App-40x40@1x.png | Bin 0 -> 1283 bytes .../AppIcon.appiconset/Icon-App-40x40@2x.png | Bin 0 -> 1895 bytes .../AppIcon.appiconset/Icon-App-40x40@3x.png | Bin 0 -> 2665 bytes .../AppIcon.appiconset/Icon-App-60x60@2x.png | Bin 0 -> 2665 bytes .../AppIcon.appiconset/Icon-App-60x60@3x.png | Bin 0 -> 3831 bytes .../AppIcon.appiconset/Icon-App-76x76@1x.png | Bin 0 -> 1888 bytes .../AppIcon.appiconset/Icon-App-76x76@2x.png | Bin 0 -> 3294 bytes .../Icon-App-83.5x83.5@2x.png | Bin 0 -> 3612 bytes .../LaunchImage.imageset/Contents.json | 23 + .../LaunchImage.imageset/LaunchImage.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/LaunchImage@2x.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/LaunchImage@3x.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/README.md | 5 + .../Runner/Base.lproj/LaunchScreen.storyboard | 37 + .../ios/Runner/Base.lproj/Main.storyboard | 26 + .../example/ios/Runner/Info.plist | 45 ++ .../example/ios/Runner/main.m | 13 + .../example/ios/RunnerTests/Info.plist | 22 + .../example/ios/RunnerTests/RunnerTests.m | 8 + .../integration_test/example/lib/main.dart | 9 + .../integration_test/example/lib/my_app.dart | 31 + .../example/lib/my_web_app.dart | 32 + .../ephemeral/Flutter-Generated.xcconfig | 11 + .../ephemeral/flutter_export_environment.sh | 12 + .../integration_test/example/macos/Podfile | 82 ++ .../macos/Runner.xcodeproj/project.pbxproj | 656 ++++++++++++++++ .../xcshareddata/xcschemes/Runner.xcscheme | 101 +++ .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../example/macos/Runner/AppDelegate.swift | 13 + .../AppIcon.appiconset/Contents.json | 68 ++ .../AppIcon.appiconset/app_icon_1024.png | Bin 0 -> 46993 bytes .../AppIcon.appiconset/app_icon_128.png | Bin 0 -> 3276 bytes .../AppIcon.appiconset/app_icon_16.png | Bin 0 -> 1429 bytes .../AppIcon.appiconset/app_icon_256.png | Bin 0 -> 5933 bytes .../AppIcon.appiconset/app_icon_32.png | Bin 0 -> 1243 bytes .../AppIcon.appiconset/app_icon_512.png | Bin 0 -> 14800 bytes .../AppIcon.appiconset/app_icon_64.png | Bin 0 -> 1874 bytes .../macos/Runner/Base.lproj/MainMenu.xib | 339 ++++++++ .../macos/Runner/Configs/AppInfo.xcconfig | 14 + .../macos/Runner/Configs/Debug.xcconfig | 2 + .../macos/Runner/Configs/Release.xcconfig | 2 + .../macos/Runner/Configs/Warnings.xcconfig | 13 + .../macos/Runner/DebugProfile.entitlements | 12 + .../example/macos/Runner/Info.plist | 32 + .../macos/Runner/MainFlutterWindow.swift | 19 + .../example/macos/Runner/Release.entitlements | 8 + .../integration_test/example/pubspec.yaml | 91 +++ .../extended_integration_test.dart | 16 + .../example/test_driver/failure.dart | 45 ++ .../example/test_driver/failure_test.dart | 24 + .../example/test_driver/integration_test.dart | 7 + .../integration_test/example/web/favicon.png | Bin 0 -> 917 bytes .../example/web/icons/Icon-192.png | Bin 0 -> 5292 bytes .../example/web/icons/Icon-512.png | Bin 0 -> 8252 bytes .../integration_test/example/web/index.html | 36 + .../example/web/manifest.json | 23 + .../integration_test_macos/CHANGELOG.md | 11 + .../ios/integration_test_macos.podspec | 21 + .../macos/Assets/.gitkeep | 0 .../macos/Classes/IntegrationTestPlugin.swift | 26 + .../macos/integration_test_macos.podspec | 20 + .../integration_test_macos/pubspec.yaml | 29 + packages/integration_test/ios/.gitignore | 37 + packages/integration_test/ios/Assets/.gitkeep | 0 .../ios/Classes/IntegrationTestIosTest.h | 26 + .../ios/Classes/IntegrationTestIosTest.m | 47 ++ .../ios/Classes/IntegrationTestPlugin.h | 29 + .../ios/Classes/IntegrationTestPlugin.m | 58 ++ .../ios/integration_test.podspec | 20 + .../integration_test/lib/_callback_io.dart | 62 ++ .../integration_test/lib/_callback_web.dart | 169 ++++ .../integration_test/lib/_extension_io.dart | 13 + .../integration_test/lib/_extension_web.dart | 32 + packages/integration_test/lib/common.dart | 298 +++++++ .../lib/integration_test.dart | 322 ++++++++ .../lib/integration_test_driver.dart | 91 +++ .../lib/integration_test_driver_extended.dart | 74 ++ packages/integration_test/pubspec.yaml | 58 ++ .../test/binding_fail_test.dart | 79 ++ .../integration_test/test/binding_test.dart | 104 +++ packages/integration_test/test/data/README.md | 4 + .../test/data/fail_test_script.dart | 24 + .../test/data/pass_test_script.dart | 25 + .../test/data/pass_then_fail_test_script.dart | 25 + .../test/response_serialization_test.dart | 51 ++ 174 files changed, 6042 insertions(+), 71 deletions(-) create mode 100644 packages/integration_test/CHANGELOG.md create mode 100644 packages/integration_test/README.md create mode 100644 packages/integration_test/android/.gitignore create mode 100644 packages/integration_test/android/build.gradle create mode 100644 packages/integration_test/android/gradle.properties create mode 100644 packages/integration_test/android/settings.gradle create mode 100644 packages/integration_test/android/src/main/AndroidManifest.xml create mode 100644 packages/integration_test/android/src/main/java/dev/flutter/plugins/integration_test/FlutterTestRunner.java create mode 100644 packages/integration_test/android/src/main/java/dev/flutter/plugins/integration_test/IntegrationTestPlugin.java create mode 100644 packages/integration_test/example/.gitignore create mode 100644 packages/integration_test/example/README.md create mode 100644 packages/integration_test/example/android/app/build.gradle create mode 100644 packages/integration_test/example/android/app/src/androidTest/java/com/example/e2e_example/EmbedderV1ActivityTest.java create mode 100644 packages/integration_test/example/android/app/src/androidTest/java/com/example/e2e_example/FlutterActivityTest.java create mode 100644 packages/integration_test/example/android/app/src/androidTest/java/com/example/e2e_example/FlutterActivityWithPermissionTest.java create mode 100644 packages/integration_test/example/android/app/src/debug/AndroidManifest.xml create mode 100644 packages/integration_test/example/android/app/src/main/AndroidManifest.xml create mode 100644 packages/integration_test/example/android/app/src/main/java/com/example/e2e_example/EmbedderV1Activity.java create mode 100644 packages/integration_test/example/android/app/src/main/res/drawable/launch_background.xml create mode 100644 packages/integration_test/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png create mode 100644 packages/integration_test/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png create mode 100644 packages/integration_test/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png create mode 100644 packages/integration_test/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 packages/integration_test/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 packages/integration_test/example/android/app/src/main/res/values/styles.xml create mode 100644 packages/integration_test/example/android/app/src/profile/AndroidManifest.xml create mode 100644 packages/integration_test/example/android/build.gradle create mode 100644 packages/integration_test/example/android/gradle.properties create mode 100644 packages/integration_test/example/android/gradle/wrapper/gradle-wrapper.properties create mode 100644 packages/integration_test/example/android/settings.gradle create mode 100644 packages/integration_test/example/integration_test/_example_test_io.dart create mode 100644 packages/integration_test/example/integration_test/_example_test_web.dart create mode 100644 packages/integration_test/example/integration_test/_extended_test_io.dart create mode 100644 packages/integration_test/example/integration_test/_extended_test_web.dart create mode 100644 packages/integration_test/example/integration_test/example_test.dart create mode 100644 packages/integration_test/example/integration_test/extended_test.dart create mode 100644 packages/integration_test/example/ios/Flutter/AppFrameworkInfo.plist create mode 100644 packages/integration_test/example/ios/Flutter/Debug.xcconfig create mode 100644 packages/integration_test/example/ios/Flutter/Release.xcconfig create mode 100644 packages/integration_test/example/ios/Podfile create mode 100644 packages/integration_test/example/ios/Runner.xcodeproj/project.pbxproj create mode 100644 packages/integration_test/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme create mode 100644 packages/integration_test/example/ios/Runner/AppDelegate.h create mode 100644 packages/integration_test/example/ios/Runner/AppDelegate.m create mode 100644 packages/integration_test/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 packages/integration_test/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png create mode 100644 packages/integration_test/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png create mode 100644 packages/integration_test/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png create mode 100644 packages/integration_test/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png create mode 100644 packages/integration_test/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png create mode 100644 packages/integration_test/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png create mode 100644 packages/integration_test/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png create mode 100644 packages/integration_test/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png create mode 100644 packages/integration_test/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png create mode 100644 packages/integration_test/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png create mode 100644 packages/integration_test/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png create mode 100644 packages/integration_test/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png create mode 100644 packages/integration_test/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png create mode 100644 packages/integration_test/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png create mode 100644 packages/integration_test/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png create mode 100644 packages/integration_test/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json create mode 100644 packages/integration_test/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png create mode 100644 packages/integration_test/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png create mode 100644 packages/integration_test/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png create mode 100644 packages/integration_test/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md create mode 100644 packages/integration_test/example/ios/Runner/Base.lproj/LaunchScreen.storyboard create mode 100644 packages/integration_test/example/ios/Runner/Base.lproj/Main.storyboard create mode 100644 packages/integration_test/example/ios/Runner/Info.plist create mode 100644 packages/integration_test/example/ios/Runner/main.m create mode 100644 packages/integration_test/example/ios/RunnerTests/Info.plist create mode 100644 packages/integration_test/example/ios/RunnerTests/RunnerTests.m create mode 100644 packages/integration_test/example/lib/main.dart create mode 100644 packages/integration_test/example/lib/my_app.dart create mode 100644 packages/integration_test/example/lib/my_web_app.dart create mode 100644 packages/integration_test/example/macos/Flutter/ephemeral/Flutter-Generated.xcconfig create mode 100755 packages/integration_test/example/macos/Flutter/ephemeral/flutter_export_environment.sh create mode 100644 packages/integration_test/example/macos/Podfile create mode 100644 packages/integration_test/example/macos/Runner.xcodeproj/project.pbxproj create mode 100644 packages/integration_test/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme create mode 100644 packages/integration_test/example/macos/Runner.xcworkspace/contents.xcworkspacedata create mode 100644 packages/integration_test/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 packages/integration_test/example/macos/Runner/AppDelegate.swift create mode 100644 packages/integration_test/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 packages/integration_test/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png create mode 100644 packages/integration_test/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png create mode 100644 packages/integration_test/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png create mode 100644 packages/integration_test/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png create mode 100644 packages/integration_test/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png create mode 100644 packages/integration_test/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png create mode 100644 packages/integration_test/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png create mode 100644 packages/integration_test/example/macos/Runner/Base.lproj/MainMenu.xib create mode 100644 packages/integration_test/example/macos/Runner/Configs/AppInfo.xcconfig create mode 100644 packages/integration_test/example/macos/Runner/Configs/Debug.xcconfig create mode 100644 packages/integration_test/example/macos/Runner/Configs/Release.xcconfig create mode 100644 packages/integration_test/example/macos/Runner/Configs/Warnings.xcconfig create mode 100644 packages/integration_test/example/macos/Runner/DebugProfile.entitlements create mode 100644 packages/integration_test/example/macos/Runner/Info.plist create mode 100644 packages/integration_test/example/macos/Runner/MainFlutterWindow.swift create mode 100644 packages/integration_test/example/macos/Runner/Release.entitlements create mode 100644 packages/integration_test/example/pubspec.yaml create mode 100644 packages/integration_test/example/test_driver/extended_integration_test.dart create mode 100644 packages/integration_test/example/test_driver/failure.dart create mode 100644 packages/integration_test/example/test_driver/failure_test.dart create mode 100644 packages/integration_test/example/test_driver/integration_test.dart create mode 100644 packages/integration_test/example/web/favicon.png create mode 100644 packages/integration_test/example/web/icons/Icon-192.png create mode 100644 packages/integration_test/example/web/icons/Icon-512.png create mode 100644 packages/integration_test/example/web/index.html create mode 100644 packages/integration_test/example/web/manifest.json create mode 100644 packages/integration_test/integration_test_macos/CHANGELOG.md create mode 100644 packages/integration_test/integration_test_macos/ios/integration_test_macos.podspec create mode 100644 packages/integration_test/integration_test_macos/macos/Assets/.gitkeep create mode 100644 packages/integration_test/integration_test_macos/macos/Classes/IntegrationTestPlugin.swift create mode 100644 packages/integration_test/integration_test_macos/macos/integration_test_macos.podspec create mode 100644 packages/integration_test/integration_test_macos/pubspec.yaml create mode 100644 packages/integration_test/ios/.gitignore create mode 100644 packages/integration_test/ios/Assets/.gitkeep create mode 100644 packages/integration_test/ios/Classes/IntegrationTestIosTest.h create mode 100644 packages/integration_test/ios/Classes/IntegrationTestIosTest.m create mode 100644 packages/integration_test/ios/Classes/IntegrationTestPlugin.h create mode 100644 packages/integration_test/ios/Classes/IntegrationTestPlugin.m create mode 100644 packages/integration_test/ios/integration_test.podspec create mode 100644 packages/integration_test/lib/_callback_io.dart create mode 100644 packages/integration_test/lib/_callback_web.dart create mode 100644 packages/integration_test/lib/_extension_io.dart create mode 100644 packages/integration_test/lib/_extension_web.dart create mode 100644 packages/integration_test/lib/common.dart create mode 100644 packages/integration_test/lib/integration_test.dart create mode 100644 packages/integration_test/lib/integration_test_driver.dart create mode 100644 packages/integration_test/lib/integration_test_driver_extended.dart create mode 100644 packages/integration_test/pubspec.yaml create mode 100644 packages/integration_test/test/binding_fail_test.dart create mode 100644 packages/integration_test/test/binding_test.dart create mode 100644 packages/integration_test/test/data/README.md create mode 100644 packages/integration_test/test/data/fail_test_script.dart create mode 100644 packages/integration_test/test/data/pass_test_script.dart create mode 100644 packages/integration_test/test/data/pass_then_fail_test_script.dart create mode 100644 packages/integration_test/test/response_serialization_test.dart diff --git a/dev/automated_tests/pubspec.yaml b/dev/automated_tests/pubspec.yaml index fb971edb90..52a5dcdc59 100644 --- a/dev/automated_tests/pubspec.yaml +++ b/dev/automated_tests/pubspec.yaml @@ -62,7 +62,7 @@ dependencies: vm_service: 5.2.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" watcher: 0.9.7+15 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" web_socket_channel: 1.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - webkit_inspection_protocol: 0.7.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + webkit_inspection_protocol: 0.7.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" yaml: 2.2.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" flutter: @@ -70,4 +70,4 @@ flutter: assets: - icon/ -# PUBSPEC CHECKSUM: 4f8b +# PUBSPEC CHECKSUM: 668c diff --git a/dev/benchmarks/complex_layout/pubspec.yaml b/dev/benchmarks/complex_layout/pubspec.yaml index 848c0c6ab2..1458d1f931 100644 --- a/dev/benchmarks/complex_layout/pubspec.yaml +++ b/dev/benchmarks/complex_layout/pubspec.yaml @@ -79,7 +79,7 @@ dev_dependencies: test_core: 0.3.12-nullsafety.9 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" watcher: 0.9.7+15 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" web_socket_channel: 1.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - webkit_inspection_protocol: 0.7.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + webkit_inspection_protocol: 0.7.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" yaml: 2.2.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" flutter: @@ -88,4 +88,4 @@ flutter: - packages/flutter_gallery_assets/people/square/ali.png - packages/flutter_gallery_assets/places/india_chettinad_silk_maker.png -# PUBSPEC CHECKSUM: 0242 +# PUBSPEC CHECKSUM: 1943 diff --git a/dev/benchmarks/macrobenchmarks/pubspec.yaml b/dev/benchmarks/macrobenchmarks/pubspec.yaml index 6b3eabb77a..789a0a3c31 100644 --- a/dev/benchmarks/macrobenchmarks/pubspec.yaml +++ b/dev/benchmarks/macrobenchmarks/pubspec.yaml @@ -39,7 +39,8 @@ dev_dependencies: flutter_test: sdk: flutter test: 1.16.0-nullsafety.9 - integration_test: 0.9.2+2 + integration_test: + sdk: flutter _fe_analyzer_shared: 7.0.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" analyzer: 0.39.17 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -79,7 +80,7 @@ dev_dependencies: test_core: 0.3.12-nullsafety.9 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" watcher: 0.9.7+15 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" web_socket_channel: 1.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - webkit_inspection_protocol: 0.7.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + webkit_inspection_protocol: 0.7.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" yaml: 2.2.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" flutter: @@ -212,4 +213,4 @@ flutter: fonts: - asset: packages/flutter_gallery_assets/fonts/GalleryIcons.ttf -# PUBSPEC CHECKSUM: 7d14 +# PUBSPEC CHECKSUM: bc9b diff --git a/dev/benchmarks/microbenchmarks/pubspec.yaml b/dev/benchmarks/microbenchmarks/pubspec.yaml index d63f24560f..8399399284 100644 --- a/dev/benchmarks/microbenchmarks/pubspec.yaml +++ b/dev/benchmarks/microbenchmarks/pubspec.yaml @@ -71,10 +71,10 @@ dependencies: vm_service: 5.2.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" watcher: 0.9.7+15 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" web_socket_channel: 1.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - webkit_inspection_protocol: 0.7.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + webkit_inspection_protocol: 0.7.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" yaml: 2.2.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" flutter: uses-material-design: true -# PUBSPEC CHECKSUM: 60ae +# PUBSPEC CHECKSUM: 77af diff --git a/dev/benchmarks/platform_views_layout/pubspec.yaml b/dev/benchmarks/platform_views_layout/pubspec.yaml index 6cc416f115..fa140799a5 100644 --- a/dev/benchmarks/platform_views_layout/pubspec.yaml +++ b/dev/benchmarks/platform_views_layout/pubspec.yaml @@ -77,7 +77,7 @@ dev_dependencies: test_core: 0.3.12-nullsafety.9 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" watcher: 0.9.7+15 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" web_socket_channel: 1.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - webkit_inspection_protocol: 0.7.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + webkit_inspection_protocol: 0.7.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" yaml: 2.2.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" flutter: @@ -86,4 +86,4 @@ flutter: - packages/flutter_gallery_assets/people/square/ali.png - packages/flutter_gallery_assets/places/india_chettinad_silk_maker.png -# PUBSPEC CHECKSUM: a59a +# PUBSPEC CHECKSUM: bc9b diff --git a/dev/benchmarks/platform_views_layout_hybrid_composition/pubspec.yaml b/dev/benchmarks/platform_views_layout_hybrid_composition/pubspec.yaml index ce52d1bace..c66e256caf 100644 --- a/dev/benchmarks/platform_views_layout_hybrid_composition/pubspec.yaml +++ b/dev/benchmarks/platform_views_layout_hybrid_composition/pubspec.yaml @@ -77,7 +77,7 @@ dev_dependencies: test_core: 0.3.12-nullsafety.9 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" watcher: 0.9.7+15 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" web_socket_channel: 1.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - webkit_inspection_protocol: 0.7.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + webkit_inspection_protocol: 0.7.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" yaml: 2.2.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" flutter: @@ -86,4 +86,4 @@ flutter: - packages/flutter_gallery_assets/people/square/ali.png - packages/flutter_gallery_assets/places/india_chettinad_silk_maker.png -# PUBSPEC CHECKSUM: a59a +# PUBSPEC CHECKSUM: bc9b diff --git a/dev/benchmarks/test_apps/stocks/pubspec.yaml b/dev/benchmarks/test_apps/stocks/pubspec.yaml index 8d20f8fe60..bc7782a318 100644 --- a/dev/benchmarks/test_apps/stocks/pubspec.yaml +++ b/dev/benchmarks/test_apps/stocks/pubspec.yaml @@ -80,9 +80,9 @@ dev_dependencies: vm_service: 5.2.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" web_socket_channel: 1.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" webdriver: 2.1.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - webkit_inspection_protocol: 0.7.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + webkit_inspection_protocol: 0.7.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" flutter: uses-material-design: true -# PUBSPEC CHECKSUM: 9b1e +# PUBSPEC CHECKSUM: b21f diff --git a/dev/bots/analyze.dart b/dev/bots/analyze.dart index 3449c3ec81..9e60c46fc6 100644 --- a/dev/bots/analyze.dart +++ b/dev/bots/analyze.dart @@ -270,6 +270,7 @@ const Set _exemptTestImports = { 'package:flutter_test/flutter_test.dart', 'hit_test.dart', 'package:test_api/src/backend/live_test.dart', + 'package:integration_test/integration_test.dart', }; Future verifyNoTestImports(String workingDirectory) async { diff --git a/dev/bots/pubspec.yaml b/dev/bots/pubspec.yaml index 34fc0177d5..bb3a11798c 100644 --- a/dev/bots/pubspec.yaml +++ b/dev/bots/pubspec.yaml @@ -68,7 +68,7 @@ dependencies: vm_service_client: 0.2.6+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" watcher: 0.9.7+15 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" web_socket_channel: 1.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - webkit_inspection_protocol: 0.7.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + webkit_inspection_protocol: 0.7.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" xml: 4.5.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" yaml: 2.2.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -76,4 +76,4 @@ dev_dependencies: mockito: 4.1.1 test_api: 0.2.19-nullsafety.6 -# PUBSPEC CHECKSUM: 07a9 +# PUBSPEC CHECKSUM: 32aa diff --git a/dev/bots/test.dart b/dev/bots/test.dart index ac2e00f0f0..304e411c8e 100644 --- a/dev/bots/test.dart +++ b/dev/bots/test.dart @@ -678,6 +678,7 @@ Future _runFrameworkTests() async { await _runFlutterTest(path.join(flutterRoot, 'examples', 'layers'), tableData: bigqueryApi?.tabledata, options: soundNullSafetyOptions); await _runFlutterTest(path.join(flutterRoot, 'dev', 'benchmarks', 'test_apps', 'stocks'), tableData: bigqueryApi?.tabledata); await _runFlutterTest(path.join(flutterRoot, 'packages', 'flutter_driver'), tableData: bigqueryApi?.tabledata, tests: [path.join('test', 'src', 'real_tests')]); + await _runFlutterTest(path.join(flutterRoot, 'packages', 'integration_test'), tableData: bigqueryApi?.tabledata); await _runFlutterTest(path.join(flutterRoot, 'packages', 'flutter_goldens'), tableData: bigqueryApi?.tabledata); await _runFlutterTest(path.join(flutterRoot, 'packages', 'flutter_localizations'), tableData: bigqueryApi?.tabledata); await _runFlutterTest(path.join(flutterRoot, 'packages', 'flutter_test'), tableData: bigqueryApi?.tabledata, options: soundNullSafetyOptions); diff --git a/dev/devicelab/pubspec.yaml b/dev/devicelab/pubspec.yaml index 85eb032320..33905cabdf 100644 --- a/dev/devicelab/pubspec.yaml +++ b/dev/devicelab/pubspec.yaml @@ -72,7 +72,7 @@ dev_dependencies: test_core: 0.3.12-nullsafety.9 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" vm_service: 5.2.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" watcher: 0.9.7+15 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - webkit_inspection_protocol: 0.7.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + webkit_inspection_protocol: 0.7.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" yaml: 2.2.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" -# PUBSPEC CHECKSUM: 8c62 +# PUBSPEC CHECKSUM: b763 diff --git a/dev/integration_tests/android_semantics_testing/pubspec.yaml b/dev/integration_tests/android_semantics_testing/pubspec.yaml index a271053fb9..af84f627e3 100644 --- a/dev/integration_tests/android_semantics_testing/pubspec.yaml +++ b/dev/integration_tests/android_semantics_testing/pubspec.yaml @@ -63,10 +63,10 @@ dependencies: watcher: 0.9.7+15 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" web_socket_channel: 1.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" webdriver: 2.1.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - webkit_inspection_protocol: 0.7.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + webkit_inspection_protocol: 0.7.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" yaml: 2.2.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" flutter: uses-material-design: true -# PUBSPEC CHECKSUM: 808d +# PUBSPEC CHECKSUM: 978e diff --git a/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/pubspec.yaml b/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/pubspec.yaml index a5130c0689..56d12241f9 100644 --- a/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/pubspec.yaml +++ b/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/pubspec.yaml @@ -93,7 +93,7 @@ dev_dependencies: watcher: 0.9.7+15 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" web_socket_channel: 1.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" webdriver: 2.1.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - webkit_inspection_protocol: 0.7.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + webkit_inspection_protocol: 0.7.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" yaml: 2.2.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" flutter: @@ -134,4 +134,4 @@ flutter: # For details regarding fonts from package dependencies, # see https://flutter.dev/custom-fonts/#from-packages -# PUBSPEC CHECKSUM: 919d +# PUBSPEC CHECKSUM: a89e diff --git a/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/pubspec.yaml b/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/pubspec.yaml index 730f4e4379..1971972c94 100644 --- a/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/pubspec.yaml +++ b/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/pubspec.yaml @@ -93,7 +93,7 @@ dev_dependencies: watcher: 0.9.7+15 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" web_socket_channel: 1.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" webdriver: 2.1.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - webkit_inspection_protocol: 0.7.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + webkit_inspection_protocol: 0.7.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" yaml: 2.2.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" flutter: @@ -134,4 +134,4 @@ flutter: # For details regarding fonts from package dependencies, # see https://flutter.dev/custom-fonts/#from-packages -# PUBSPEC CHECKSUM: 919d +# PUBSPEC CHECKSUM: a89e diff --git a/dev/integration_tests/android_views/pubspec.yaml b/dev/integration_tests/android_views/pubspec.yaml index 728a132e7e..e5a05f7c0f 100644 --- a/dev/integration_tests/android_views/pubspec.yaml +++ b/dev/integration_tests/android_views/pubspec.yaml @@ -86,10 +86,10 @@ dev_dependencies: test_core: 0.3.12-nullsafety.9 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" watcher: 0.9.7+15 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" web_socket_channel: 1.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - webkit_inspection_protocol: 0.7.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + webkit_inspection_protocol: 0.7.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" yaml: 2.2.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" flutter: uses-material-design: true -# PUBSPEC CHECKSUM: d6c4 +# PUBSPEC CHECKSUM: 1ac5 diff --git a/dev/integration_tests/channels/pubspec.yaml b/dev/integration_tests/channels/pubspec.yaml index a8ed12cacc..a184675ace 100644 --- a/dev/integration_tests/channels/pubspec.yaml +++ b/dev/integration_tests/channels/pubspec.yaml @@ -65,10 +65,10 @@ dependencies: watcher: 0.9.7+15 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" web_socket_channel: 1.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" webdriver: 2.1.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - webkit_inspection_protocol: 0.7.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + webkit_inspection_protocol: 0.7.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" yaml: 2.2.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" flutter: uses-material-design: true -# PUBSPEC CHECKSUM: 808d +# PUBSPEC CHECKSUM: 978e diff --git a/dev/integration_tests/external_ui/pubspec.yaml b/dev/integration_tests/external_ui/pubspec.yaml index b5915800e8..7c649bf78b 100644 --- a/dev/integration_tests/external_ui/pubspec.yaml +++ b/dev/integration_tests/external_ui/pubspec.yaml @@ -65,10 +65,10 @@ dependencies: watcher: 0.9.7+15 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" web_socket_channel: 1.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" webdriver: 2.1.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - webkit_inspection_protocol: 0.7.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + webkit_inspection_protocol: 0.7.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" yaml: 2.2.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" flutter: uses-material-design: true -# PUBSPEC CHECKSUM: 808d +# PUBSPEC CHECKSUM: 978e diff --git a/dev/integration_tests/flavors/pubspec.yaml b/dev/integration_tests/flavors/pubspec.yaml index 352302b0d6..b00f6b4e22 100644 --- a/dev/integration_tests/flavors/pubspec.yaml +++ b/dev/integration_tests/flavors/pubspec.yaml @@ -65,10 +65,10 @@ dependencies: watcher: 0.9.7+15 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" web_socket_channel: 1.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" webdriver: 2.1.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - webkit_inspection_protocol: 0.7.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + webkit_inspection_protocol: 0.7.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" yaml: 2.2.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" flutter: uses-material-design: true -# PUBSPEC CHECKSUM: 808d +# PUBSPEC CHECKSUM: 978e diff --git a/dev/integration_tests/flutter_driver_screenshot_test/pubspec.yaml b/dev/integration_tests/flutter_driver_screenshot_test/pubspec.yaml index 623647380f..c6a4c8ac68 100644 --- a/dev/integration_tests/flutter_driver_screenshot_test/pubspec.yaml +++ b/dev/integration_tests/flutter_driver_screenshot_test/pubspec.yaml @@ -71,7 +71,7 @@ dev_dependencies: test_core: 0.3.12-nullsafety.9 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" watcher: 0.9.7+15 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" web_socket_channel: 1.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - webkit_inspection_protocol: 0.7.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + webkit_inspection_protocol: 0.7.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" yaml: 2.2.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" flutter: @@ -79,4 +79,4 @@ flutter: assets: - assets/ -# PUBSPEC CHECKSUM: 22db +# PUBSPEC CHECKSUM: 39dc diff --git a/dev/integration_tests/flutter_gallery/pubspec.yaml b/dev/integration_tests/flutter_gallery/pubspec.yaml index ca88a1c69c..952fd1a786 100644 --- a/dev/integration_tests/flutter_gallery/pubspec.yaml +++ b/dev/integration_tests/flutter_gallery/pubspec.yaml @@ -50,7 +50,8 @@ dev_dependencies: flutter_goldens: sdk: flutter test: 1.16.0-nullsafety.9 - integration_test: 0.9.2+2 + integration_test: + sdk: flutter _fe_analyzer_shared: 7.0.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" analyzer: 0.39.17 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -98,7 +99,7 @@ dev_dependencies: watcher: 0.9.7+15 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" web_socket_channel: 1.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" webdriver: 2.1.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - webkit_inspection_protocol: 0.7.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + webkit_inspection_protocol: 0.7.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" yaml: 2.2.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" flutter: @@ -272,4 +273,4 @@ flutter: - asset: packages/flutter_gallery_assets/fonts/merriweather/Merriweather-Regular.ttf - asset: packages/flutter_gallery_assets/fonts/merriweather/Merriweather-Light.ttf -# PUBSPEC CHECKSUM: 5602 +# PUBSPEC CHECKSUM: b589 diff --git a/dev/integration_tests/hybrid_android_views/pubspec.yaml b/dev/integration_tests/hybrid_android_views/pubspec.yaml index ab1b889e1c..3d8a5d3335 100644 --- a/dev/integration_tests/hybrid_android_views/pubspec.yaml +++ b/dev/integration_tests/hybrid_android_views/pubspec.yaml @@ -86,10 +86,10 @@ dev_dependencies: test_core: 0.3.12-nullsafety.9 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" watcher: 0.9.7+15 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" web_socket_channel: 1.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - webkit_inspection_protocol: 0.7.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + webkit_inspection_protocol: 0.7.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" yaml: 2.2.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" flutter: uses-material-design: true -# PUBSPEC CHECKSUM: d6c4 +# PUBSPEC CHECKSUM: 1ac5 diff --git a/dev/integration_tests/image_loading/pubspec.yaml b/dev/integration_tests/image_loading/pubspec.yaml index 320f8cd032..700a91b49a 100644 --- a/dev/integration_tests/image_loading/pubspec.yaml +++ b/dev/integration_tests/image_loading/pubspec.yaml @@ -58,10 +58,10 @@ dependencies: vm_service: 5.2.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" watcher: 0.9.7+15 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" web_socket_channel: 1.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - webkit_inspection_protocol: 0.7.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + webkit_inspection_protocol: 0.7.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" yaml: 2.2.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" flutter: uses-material-design: true -# PUBSPEC CHECKSUM: 3664 +# PUBSPEC CHECKSUM: 4d65 diff --git a/dev/integration_tests/ios_platform_view_tests/pubspec.yaml b/dev/integration_tests/ios_platform_view_tests/pubspec.yaml index 5fc5f7ca30..2b7fcb7cdd 100644 --- a/dev/integration_tests/ios_platform_view_tests/pubspec.yaml +++ b/dev/integration_tests/ios_platform_view_tests/pubspec.yaml @@ -72,7 +72,7 @@ dev_dependencies: watcher: 0.9.7+15 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" web_socket_channel: 1.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" webdriver: 2.1.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - webkit_inspection_protocol: 0.7.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + webkit_inspection_protocol: 0.7.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" yaml: 2.2.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" flutter: @@ -82,4 +82,4 @@ flutter: # the material Icons class. uses-material-design: true -# PUBSPEC CHECKSUM: f0fa +# PUBSPEC CHECKSUM: 08fb diff --git a/dev/integration_tests/platform_interaction/pubspec.yaml b/dev/integration_tests/platform_interaction/pubspec.yaml index a7836a370d..e2686a3fa6 100644 --- a/dev/integration_tests/platform_interaction/pubspec.yaml +++ b/dev/integration_tests/platform_interaction/pubspec.yaml @@ -65,10 +65,10 @@ dependencies: watcher: 0.9.7+15 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" web_socket_channel: 1.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" webdriver: 2.1.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - webkit_inspection_protocol: 0.7.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + webkit_inspection_protocol: 0.7.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" yaml: 2.2.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" flutter: uses-material-design: true -# PUBSPEC CHECKSUM: 808d +# PUBSPEC CHECKSUM: 978e diff --git a/dev/integration_tests/ui/pubspec.yaml b/dev/integration_tests/ui/pubspec.yaml index a85d9c274c..a8e78325c0 100644 --- a/dev/integration_tests/ui/pubspec.yaml +++ b/dev/integration_tests/ui/pubspec.yaml @@ -66,7 +66,7 @@ dependencies: watcher: 0.9.7+15 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" web_socket_channel: 1.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" webdriver: 2.1.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - webkit_inspection_protocol: 0.7.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + webkit_inspection_protocol: 0.7.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" xml: 4.5.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" yaml: 2.2.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -81,4 +81,4 @@ dev_dependencies: flutter: uses-material-design: true -# PUBSPEC CHECKSUM: bf2a +# PUBSPEC CHECKSUM: ea2b diff --git a/dev/integration_tests/web_e2e_tests/pubspec.yaml b/dev/integration_tests/web_e2e_tests/pubspec.yaml index 6c719bbe8d..2a8433f782 100644 --- a/dev/integration_tests/web_e2e_tests/pubspec.yaml +++ b/dev/integration_tests/web_e2e_tests/pubspec.yaml @@ -19,7 +19,8 @@ dev_dependencies: sdk: flutter flutter_test: sdk: flutter - integration_test: 0.9.2+2 + integration_test: + sdk: flutter http: 0.12.2 test: 1.16.0-nullsafety.9 @@ -73,7 +74,7 @@ dev_dependencies: watcher: 0.9.7+15 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" web_socket_channel: 1.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" webdriver: 2.1.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - webkit_inspection_protocol: 0.7.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + webkit_inspection_protocol: 0.7.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" yaml: 2.2.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" -# PUBSPEC CHECKSUM: e2b2 +# PUBSPEC CHECKSUM: 273a diff --git a/dev/snippets/pubspec.yaml b/dev/snippets/pubspec.yaml index 18d164fd0c..95f8b6f026 100644 --- a/dev/snippets/pubspec.yaml +++ b/dev/snippets/pubspec.yaml @@ -68,7 +68,7 @@ dev_dependencies: test_core: 0.3.12-nullsafety.9 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" vm_service: 5.2.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" web_socket_channel: 1.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - webkit_inspection_protocol: 0.7.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + webkit_inspection_protocol: 0.7.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" executables: snippets: null @@ -99,4 +99,4 @@ executables: vm_service_client: 0.2.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" web_socket_channel: 1.0.9 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" -# PUBSPEC CHECKSUM: 552c +# PUBSPEC CHECKSUM: 6c2d diff --git a/dev/tools/pubspec.yaml b/dev/tools/pubspec.yaml index 2b7c36aef4..012be369e5 100644 --- a/dev/tools/pubspec.yaml +++ b/dev/tools/pubspec.yaml @@ -65,7 +65,7 @@ dev_dependencies: vm_service: 5.2.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" watcher: 0.9.7+15 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" web_socket_channel: 1.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - webkit_inspection_protocol: 0.7.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + webkit_inspection_protocol: 0.7.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" yaml: 2.2.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" -# PUBSPEC CHECKSUM: 3bac +# PUBSPEC CHECKSUM: 52ad diff --git a/examples/hello_world/pubspec.yaml b/examples/hello_world/pubspec.yaml index 99e559fc8c..ccedd1c4bc 100644 --- a/examples/hello_world/pubspec.yaml +++ b/examples/hello_world/pubspec.yaml @@ -71,7 +71,7 @@ dev_dependencies: watcher: 0.9.7+15 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" web_socket_channel: 1.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" webdriver: 2.1.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - webkit_inspection_protocol: 0.7.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + webkit_inspection_protocol: 0.7.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" yaml: 2.2.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" -# PUBSPEC CHECKSUM: f0fa +# PUBSPEC CHECKSUM: 08fb diff --git a/examples/platform_channel/pubspec.yaml b/examples/platform_channel/pubspec.yaml index 640dae8348..8781e8599e 100644 --- a/examples/platform_channel/pubspec.yaml +++ b/examples/platform_channel/pubspec.yaml @@ -71,10 +71,10 @@ dev_dependencies: watcher: 0.9.7+15 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" web_socket_channel: 1.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" webdriver: 2.1.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - webkit_inspection_protocol: 0.7.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + webkit_inspection_protocol: 0.7.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" yaml: 2.2.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" flutter: uses-material-design: true -# PUBSPEC CHECKSUM: f0fa +# PUBSPEC CHECKSUM: 08fb diff --git a/examples/platform_channel_swift/pubspec.yaml b/examples/platform_channel_swift/pubspec.yaml index 7660e4695c..b2bd03d112 100644 --- a/examples/platform_channel_swift/pubspec.yaml +++ b/examples/platform_channel_swift/pubspec.yaml @@ -71,10 +71,10 @@ dev_dependencies: watcher: 0.9.7+15 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" web_socket_channel: 1.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" webdriver: 2.1.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - webkit_inspection_protocol: 0.7.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + webkit_inspection_protocol: 0.7.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" yaml: 2.2.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" flutter: uses-material-design: true -# PUBSPEC CHECKSUM: f0fa +# PUBSPEC CHECKSUM: 08fb diff --git a/packages/_flutter_web_build_script/pubspec.yaml b/packages/_flutter_web_build_script/pubspec.yaml index 5f346d97a7..5c4fc3fdc4 100644 --- a/packages/_flutter_web_build_script/pubspec.yaml +++ b/packages/_flutter_web_build_script/pubspec.yaml @@ -86,11 +86,11 @@ dependencies: vm_service: 5.2.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" watcher: 0.9.7+15 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" web_socket_channel: 1.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - webkit_inspection_protocol: 0.7.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + webkit_inspection_protocol: 0.7.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" yaml: 2.2.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" dartdoc: # Exclude this package from the hosted API docs. nodoc: true -# PUBSPEC CHECKSUM: 8ffd +# PUBSPEC CHECKSUM: a6fe diff --git a/packages/flutter_driver/pubspec.yaml b/packages/flutter_driver/pubspec.yaml index bc06737f57..ca62cf3fd6 100644 --- a/packages/flutter_driver/pubspec.yaml +++ b/packages/flutter_driver/pubspec.yaml @@ -78,7 +78,7 @@ dev_dependencies: source_maps: 0.10.10-nullsafety.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" test_core: 0.3.12-nullsafety.9 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" watcher: 0.9.7+15 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - webkit_inspection_protocol: 0.7.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + webkit_inspection_protocol: 0.7.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" yaml: 2.2.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" -# PUBSPEC CHECKSUM: fd3a +# PUBSPEC CHECKSUM: 153b diff --git a/packages/flutter_tools/lib/src/commands/update_packages.dart b/packages/flutter_tools/lib/src/commands/update_packages.dart index d090e33012..a343c965a9 100644 --- a/packages/flutter_tools/lib/src/commands/update_packages.dart +++ b/packages/flutter_tools/lib/src/commands/update_packages.dart @@ -184,7 +184,7 @@ class UpdatePackagesCommand extends FlutterCommand { ); } - // "consumer" packages are those that constitute our public API (e.g. flutter, flutter_test, flutter_driver, flutter_localizations). + // "consumer" packages are those that constitute our public API (e.g. flutter, flutter_test, flutter_driver, flutter_localizations, integration_test). if (isConsumerOnly) { if (!isPrintTransitiveClosure) { throwToolExit( @@ -192,7 +192,7 @@ class UpdatePackagesCommand extends FlutterCommand { ); } // Only retain flutter, flutter_test, flutter_driver, and flutter_localizations. - const List consumerPackages = ['flutter', 'flutter_test', 'flutter_driver', 'flutter_localizations']; + const List consumerPackages = ['flutter', 'flutter_test', 'flutter_driver', 'flutter_localizations', 'integration_test']; // ensure we only get flutter/packages packages.retainWhere((Directory directory) { return consumerPackages.any((String package) { diff --git a/packages/flutter_tools/pubspec.yaml b/packages/flutter_tools/pubspec.yaml index 47b3fc1046..e538fed92a 100644 --- a/packages/flutter_tools/pubspec.yaml +++ b/packages/flutter_tools/pubspec.yaml @@ -30,7 +30,7 @@ dependencies: stack_trace: 1.10.0-nullsafety.6 usage: 3.4.2 webdriver: 2.1.2 - webkit_inspection_protocol: 0.7.3 + webkit_inspection_protocol: 0.7.4 xml: 4.5.1 yaml: 2.2.1 native_stack_traces: 0.3.7 @@ -113,4 +113,4 @@ dartdoc: # Exclude this package from the hosted API docs. nodoc: true -# PUBSPEC CHECKSUM: 5437 +# PUBSPEC CHECKSUM: 7f38 diff --git a/packages/fuchsia_remote_debug_protocol/pubspec.yaml b/packages/fuchsia_remote_debug_protocol/pubspec.yaml index bdd1238e18..9954b5f159 100644 --- a/packages/fuchsia_remote_debug_protocol/pubspec.yaml +++ b/packages/fuchsia_remote_debug_protocol/pubspec.yaml @@ -76,7 +76,7 @@ dev_dependencies: source_maps: 0.10.10-nullsafety.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" test_core: 0.3.12-nullsafety.9 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" watcher: 0.9.7+15 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - webkit_inspection_protocol: 0.7.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + webkit_inspection_protocol: 0.7.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" yaml: 2.2.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" -# PUBSPEC CHECKSUM: d4ed +# PUBSPEC CHECKSUM: ebee diff --git a/packages/integration_test/CHANGELOG.md b/packages/integration_test/CHANGELOG.md new file mode 100644 index 0000000000..d92de4f249 --- /dev/null +++ b/packages/integration_test/CHANGELOG.md @@ -0,0 +1,228 @@ +# CHANGELOG + +This changelog was discontinued after version 0.9.2+2, when the package started +to vend from the Flutter SDK rather than pub. + +It is maintained here for historical purposes only. + +## 0.9.2+2 + +* Broaden the constraint on vm_service. + +## 0.9.2+1 + +* Update android compileSdkVersion to 29. + +## 0.9.2 + +* Add `watchPerformance` for performance test. + +## 0.9.1 + +* Keep handling deprecated Android v1 classes for backward compatibility. + +## 0.9.0 + +* Add screenshot capability to web tests. + +## 0.8.2 + +* Add support to get timeline. + +## 0.8.1 + +* Show stack trace of widget test errors on the platform side +* Fix method channel name for iOS + +## 0.8.0 + +* Rename plugin to integration_test. + +## 0.7.0 + +* Move utilities for tracking frame performance in an e2e test to `flutter_test`. + +## 0.6.3 + +* Add customizable `flutter_driver` adaptor. +* Add utilities for tracking frame performance in an e2e test. + +## 0.6.2+1 + +* Fix incorrect test results when one test passes then another fails + +## 0.6.2 + +* Fix `setSurfaceSize` for e2e tests + +## 0.6.1 + +* Added `data` in the reported json. + +## 0.6.0 + +* **Breaking change** `E2EPlugin` exports a `Future` for `testResults`. + +## 0.5.0+1 + +* Fixed the device pixel ratio problem. + +## 0.5.0 + +* **Breaking change** by default, tests will use the device window size. + Tests can still override the window size by using the `setSurfaceSize` method. +* **Breaking change** If using Flutter 1.19.0-2.0.pre.196 or greater, the + `testTextInput` will no longer automatically register. +* **Breaking change** If using Flutter 1.19.0-2.0.pre.196 or greater, the + `HttpOverrides` will no longer be set by default. +* Minor formatting changes to Dart code. + +## 0.4.3+3 + +* Fixed code snippet in readme that referenced a non-existent `result` variable. + +## 0.4.3+2 + +* Bumps AGP to 3.6.3 +* Changes android-retrofuture dependency type to "implementation" + +## 0.4.3+1 + +* Post-v2 Android embedding cleanup. + +## 0.4.3 + +* Uses CompletableFuture from android-retrofuture allow compatibility with API < 24. + +## 0.4.2 + +* Adds support for Android E2E tests that utilize other @Rule's, like GrantPermissionRule. +* Fix CocoaPods podspec lint warnings. + +## 0.4.1 + +* Remove Android dependencies fallback. +* Require Flutter SDK 1.12.13+hotfix.5 or greater. + +## 0.4.0 + +* **Breaking change** Driver request_data call's response has changed to + encapsulate the failure details. +* Details for failure cases are added: failed method name, stack trace. + +## 0.3.0+1 + +* Replace deprecated `getFlutterEngine` call on Android. + +## 0.3.0 + +* Updates documentation to instruct developers not to launch the activity since + we are doing it for them. +* Renames `FlutterRunner` to `FlutterTestRunner` to avoid conflict with Fuchsia. + +## 0.2.4+4 + +* Fixed a hang that occurred on platforms that don't have a `MethodChannel` listener registered.. + +## 0.2.4+3 + +* Fixed code snippet in the readme under the "Using Flutter driver to run tests" section. + +## 0.2.4+2 + +* Make the pedantic dev_dependency explicit. + +## 0.2.4+1 + +* Registering web service extension for using e2e with web. + +## 0.2.4 + +* Fixed problem with XCTest in XCode 11.3 where the testing bundles were getting + opened multiple times which interfered with the singleton logic for E2EPlugin. + +## 0.2.3+1 + +* Added a driver test for failure behavior. + +## 0.2.3 + +* Updates `E2EPlugin` and add skeleton iOS test case `E2EIosTest`. +* Adds instructions to README.md about e2e testing on iOS devices. +* Adds iOS e2e testing to example. + +## 0.2.2+3 + +* Remove the deprecated `author:` field from pubspec.yaml +* Migrate the plugin to the pubspec platforms manifest. +* Require Flutter SDK 1.10.0 or greater. + +## 0.2.2+2 + +* Adds an android dummy project to silence warnings and removes unnecessary + .gitignore files. + +## 0.2.2+1 + +* Fix pedantic lints. Adds a missing await in the example test and some missing + documentation. + +## 0.2.2 + +* Added a stub macos implementation +* Added a macos example + +## 0.2.1+1 + +* Updated README. + +## 0.2.1 + +* Support the v2 Android embedder. +* Print a warning if the plugin is not registered. +* Updated method channel name. +* Set a Flutter minimum SDK version. + +## 0.2.0+1 + +* Updated README. + +## 0.2.0 + +* Renamed package from instrumentation_adapter to e2e. +* Refactored example app test. +* **Breaking change**. Renamed `InstrumentationAdapterFlutterBinding` to + `IntegrationTestWidgetsFlutterBinding`. +* Updated README. + +## 0.1.4 + +* Migrate example to AndroidX. +* Define clang module for iOS. + +## 0.1.3 + +* Added example app. +* Added stub iOS implementation. +* Updated README. +* No longer throws errors when running tests on the host. + +## 0.1.2 + +* Added support for running tests using Flutter driver. + +## 0.1.1 + +* Updates about using *androidx* library. + +## 0.1.0 + +* Update boilerplate test to use `@Rule` instead of `FlutterTest`. + +## 0.0.2 + +* Document current usage instructions, which require adding a Java test file. + +## 0.0.1 + +* Initial release diff --git a/packages/integration_test/README.md b/packages/integration_test/README.md new file mode 100644 index 0000000000..be08a722bc --- /dev/null +++ b/packages/integration_test/README.md @@ -0,0 +1,212 @@ +# integration_test + +This package enables self-driving testing of Flutter code on devices and emulators. +It adapts flutter_test results into a format that is compatible with `flutter drive` +and native Android instrumentation testing. + +## Usage + +Add a dependency on the `integration_test` and `flutter_test` package in the +`dev_dependencies` section of `pubspec.yaml`. For plugins, do this in the +`pubspec.yaml` of the example app. + +Create a `integration_test/` directory for your package. In this directory, +create a `_test.dart`, using the following as a starting point to make +assertions. + +```dart +import 'package:flutter_test/flutter_test.dart'; +import 'package:integration_test/integration_test.dart'; + +void main() { + IntegrationTestWidgetsFlutterBinding.ensureInitialized(); + + testWidgets("failing test example", (WidgetTester tester) async { + expect(2 + 2, equals(5)); + }); +} +``` + +### Driver Entrypoint + +An accompanying driver script will be needed that can be shared across all +integration tests. Create a file named `integration_test.dart` in the +`test_driver/` directory with the following contents: + +```dart +import 'package:integration_test/integration_test_driver.dart'; + +Future main() => integrationDriver(); +``` + +You can also use different driver scripts to customize the behavior of the app +under test. For example, `FlutterDriver` can also be parameterized with +different [options](https://api.flutter.dev/flutter/flutter_driver/FlutterDriver/connect.html). +See the [extended driver](https://github.com/flutter/plugins/tree/master/packages/integration_test/example/test_driver/integration_test_extended_driver.dart) for an example. + +### Package Structure + +Your package should have a structure that looks like this: + +``` +lib/ + ... +integration_test/ + foo_test.dart + bar_test.dart +test/ + # Other unit tests go here. +test_driver/ + integration_test.dart +``` + +[Example](https://github.com/flutter/plugins/tree/master/packages/integration_test/example) + +## Using Flutter Driver to Run Tests + +These tests can be launched with the `flutter drive` command. + +To run the `integration_test/foo_test.dart` test with the +`test_driver/integration_test.dart` driver, use the following command: + +```sh +flutter drive \ + --driver=test_driver/integration_test.dart \ + --target=integration_test/foo_test.dart +``` + +### Web + +Make sure you have [enabled web support](https://flutter.dev/docs/get-started/web#set-up) +then [download and run](https://flutter.dev/docs/cookbook/testing/integration/introduction#6b-web) +the web driver in another process. + +Use following command to execute the tests: + +```sh +flutter drive \ + --driver=test_driver/integration_test.dart \ + --target=integration_test/foo_test.dart \ + -d web-server +``` + +## Android Device Testing + +Create an instrumentation test file in your application's +**android/app/src/androidTest/java/com/example/myapp/** directory (replacing +com, example, and myapp with values from your app's package name). You can name +this test file `MainActivityTest.java` or another name of your choice. + +```java +package com.example.myapp; + +import androidx.test.rule.ActivityTestRule; +import dev.flutter.plugins.integration_test.FlutterTestRunner; +import org.junit.Rule; +import org.junit.runner.RunWith; + +@RunWith(FlutterTestRunner.class) +public class MainActivityTest { + @Rule + public ActivityTestRule rule = new ActivityTestRule<>(MainActivity.class, true, false); +} +``` + +Update your application's **myapp/android/app/build.gradle** to make sure it +uses androidx's version of `AndroidJUnitRunner` and has androidx libraries as a +dependency. + +```gradle +android { + ... + defaultConfig { + ... + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } +} + +dependencies { + testImplementation 'junit:junit:4.12' + + // https://developer.android.com/jetpack/androidx/releases/test/#1.2.0 + androidTestImplementation 'androidx.test:runner:1.2.0' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' +} +``` + +To run `integration_test/foo_test.dart` on a local Android device (emulated or +physical): + +```sh +./gradlew app:connectedAndroidTest -Ptarget=`pwd`/../integration_test/foo_test.dart +``` + +## Firebase Test Lab + +If this is your first time testing with Firebase Test Lab, you'll need to follow +the guides in the [Firebase test lab +documentation](https://firebase.google.com/docs/test-lab/?gclid=EAIaIQobChMIs5qVwqW25QIV8iCtBh3DrwyUEAAYASAAEgLFU_D_BwE) +to set up a project. + +To run a test on Android devices using Firebase Test Lab, use gradle commands to build an +instrumentation test for Android, after creating `androidTest` as suggested in the last section. + +```bash +pushd android +# flutter build generates files in android/ for building the app +flutter build apk +./gradlew app:assembleAndroidTest +./gradlew app:assembleDebug -Ptarget=.dart +popd +``` + +Upload the build apks Firebase Test Lab, making sure to replace , +, , and with your values. + +```bash +gcloud auth activate-service-account --key-file= +gcloud --quiet config set project +gcloud firebase test android run --type instrumentation \ + --app build/app/outputs/apk/debug/app-debug.apk \ + --test build/app/outputs/apk/androidTest/debug/app-debug-androidTest.apk\ + --timeout 2m \ + --results-bucket= \ + --results-dir= +``` + +You can pass additional parameters on the command line, such as the +devices you want to test on. See +[gcloud firebase test android run](https://cloud.google.com/sdk/gcloud/reference/firebase/test/android/run). + +## iOS Device Testing + +You need to change `iOS/Podfile` to avoid test target statically linking to the plugins. One way is to +link all of the plugins dynamically: + +``` +target 'Runner' do + use_frameworks! + ... +end +``` + +To run `integration_test/foo_test.dart` on your iOS device, rebuild your iOS +targets with Flutter tool. + +```sh +# Pass --simulator if building for the simulator. +flutter build ios integration_test/foo_test.dart +``` + +Open Xcode project (by default, it's `ios/Runner.xcodeproj`). Create a test target +(navigating `File > New > Target...` and set up the values) and a test file `RunnerTests.m` and +change the code. You can change `RunnerTests.m` to the name of your choice. + +```objective-c +#import +#import + +INTEGRATION_TEST_IOS_RUNNER(RunnerTests) +``` + +Now you can start RunnerTests to kick-off integration tests! diff --git a/packages/integration_test/android/.gitignore b/packages/integration_test/android/.gitignore new file mode 100644 index 0000000000..c6cbe562a4 --- /dev/null +++ b/packages/integration_test/android/.gitignore @@ -0,0 +1,8 @@ +*.iml +.gradle +/local.properties +/.idea/workspace.xml +/.idea/libraries +.DS_Store +/build +/captures diff --git a/packages/integration_test/android/build.gradle b/packages/integration_test/android/build.gradle new file mode 100644 index 0000000000..2318d33b15 --- /dev/null +++ b/packages/integration_test/android/build.gradle @@ -0,0 +1,48 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +group 'com.example.integration_test' +version '1.0-SNAPSHOT' + +buildscript { + repositories { + google() + jcenter() + } + + dependencies { + classpath 'com.android.tools.build:gradle:3.6.3' + } +} + +rootProject.allprojects { + repositories { + google() + jcenter() + } +} + +apply plugin: 'com.android.library' + +android { + compileSdkVersion 29 + + defaultConfig { + minSdkVersion 16 + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + lintOptions { + disable 'InvalidPackage' + } + dependencies { + api 'junit:junit:4.12' + + // https://developer.android.com/jetpack/androidx/releases/test/#1.2.0 + api 'androidx.test:runner:1.2.0' + api 'androidx.test:rules:1.2.0' + api 'androidx.test.espresso:espresso-core:3.2.0' + + implementation 'com.google.guava:guava:28.1-android' + } +} diff --git a/packages/integration_test/android/gradle.properties b/packages/integration_test/android/gradle.properties new file mode 100644 index 0000000000..8bd86f6805 --- /dev/null +++ b/packages/integration_test/android/gradle.properties @@ -0,0 +1 @@ +org.gradle.jvmargs=-Xmx1536M diff --git a/packages/integration_test/android/settings.gradle b/packages/integration_test/android/settings.gradle new file mode 100644 index 0000000000..29941fd33e --- /dev/null +++ b/packages/integration_test/android/settings.gradle @@ -0,0 +1,5 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +rootProject.name = 'integrationTest' diff --git a/packages/integration_test/android/src/main/AndroidManifest.xml b/packages/integration_test/android/src/main/AndroidManifest.xml new file mode 100644 index 0000000000..b362178b96 --- /dev/null +++ b/packages/integration_test/android/src/main/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/packages/integration_test/android/src/main/java/dev/flutter/plugins/integration_test/FlutterTestRunner.java b/packages/integration_test/android/src/main/java/dev/flutter/plugins/integration_test/FlutterTestRunner.java new file mode 100644 index 0000000000..8aca3cdce4 --- /dev/null +++ b/packages/integration_test/android/src/main/java/dev/flutter/plugins/integration_test/FlutterTestRunner.java @@ -0,0 +1,87 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package dev.flutter.plugins.integration_test; + +import android.util.Log; +import androidx.test.rule.ActivityTestRule; +import java.lang.reflect.Field; +import java.util.Map; +import java.util.concurrent.ExecutionException; +import org.junit.Rule; +import org.junit.rules.TestRule; +import org.junit.runner.Description; +import org.junit.runner.Runner; +import org.junit.runner.notification.Failure; +import org.junit.runner.notification.RunNotifier; + +public class FlutterTestRunner extends Runner { + + private static final String TAG = "FlutterTestRunner"; + + final Class testClass; + TestRule rule = null; + + public FlutterTestRunner(Class testClass) { + super(); + this.testClass = testClass; + + // Look for an `ActivityTestRule` annotated `@Rule` and invoke `launchActivity()` + Field[] fields = testClass.getDeclaredFields(); + for (Field field : fields) { + if (field.isAnnotationPresent(Rule.class)) { + try { + Object instance = testClass.newInstance(); + if (field.get(instance) instanceof ActivityTestRule) { + rule = (TestRule) field.get(instance); + break; + } + } catch (InstantiationException | IllegalAccessException e) { + // This might occur if the developer did not make the rule public. + // We could call field.setAccessible(true) but it seems better to throw. + throw new RuntimeException("Unable to access activity rule", e); + } + } + } + } + + @Override + public Description getDescription() { + return Description.createTestDescription(testClass, "Flutter Tests"); + } + + @Override + public void run(RunNotifier notifier) { + if (rule == null) { + throw new RuntimeException("Unable to run tests due to missing activity rule"); + } + try { + if (rule instanceof ActivityTestRule) { + ((ActivityTestRule) rule).launchActivity(null); + } + } catch (RuntimeException e) { + Log.v(TAG, "launchActivity failed, possibly because the activity was already running. " + e); + Log.v( + TAG, + "Try disabling auto-launch of the activity, e.g. ActivityTestRule<>(MainActivity.class, true, false);"); + } + Map results = null; + try { + results = IntegrationTestPlugin.testResults.get(); + } catch (ExecutionException | InterruptedException e) { + throw new IllegalThreadStateException("Unable to get test results"); + } + + for (String name : results.keySet()) { + Description d = Description.createTestDescription(testClass, name); + notifier.fireTestStarted(d); + String outcome = results.get(name); + if (!outcome.equals("success")) { + Exception dummyException = new Exception(outcome); + notifier.fireTestFailure(new Failure(d, dummyException)); + } + notifier.fireTestFinished(d); + } + } +} diff --git a/packages/integration_test/android/src/main/java/dev/flutter/plugins/integration_test/IntegrationTestPlugin.java b/packages/integration_test/android/src/main/java/dev/flutter/plugins/integration_test/IntegrationTestPlugin.java new file mode 100644 index 0000000000..81b557b824 --- /dev/null +++ b/packages/integration_test/android/src/main/java/dev/flutter/plugins/integration_test/IntegrationTestPlugin.java @@ -0,0 +1,61 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package dev.flutter.plugins.integration_test; + +import android.content.Context; +import com.google.common.util.concurrent.SettableFuture; +import io.flutter.embedding.engine.plugins.FlutterPlugin; +import io.flutter.plugin.common.BinaryMessenger; +import io.flutter.plugin.common.MethodCall; +import io.flutter.plugin.common.MethodChannel; +import io.flutter.plugin.common.MethodChannel.MethodCallHandler; +import io.flutter.plugin.common.MethodChannel.Result; +import java.util.Map; +import java.util.concurrent.Future; + +/** IntegrationTestPlugin */ +public class IntegrationTestPlugin implements MethodCallHandler, FlutterPlugin { + private MethodChannel methodChannel; + + private static final SettableFuture> testResultsSettable = + SettableFuture.create(); + public static final Future> testResults = testResultsSettable; + + private static final String CHANNEL = "plugins.flutter.io/integration_test"; + + /** Plugin registration. */ + @SuppressWarnings("deprecation") + public static void registerWith(io.flutter.plugin.common.PluginRegistry.Registrar registrar) { + final IntegrationTestPlugin instance = new IntegrationTestPlugin(); + instance.onAttachedToEngine(registrar.context(), registrar.messenger()); + } + + @Override + public void onAttachedToEngine(FlutterPluginBinding binding) { + onAttachedToEngine(binding.getApplicationContext(), binding.getBinaryMessenger()); + } + + private void onAttachedToEngine(Context unusedApplicationContext, BinaryMessenger messenger) { + methodChannel = new MethodChannel(messenger, CHANNEL); + methodChannel.setMethodCallHandler(this); + } + + @Override + public void onDetachedFromEngine(FlutterPluginBinding binding) { + methodChannel.setMethodCallHandler(null); + methodChannel = null; + } + + @Override + public void onMethodCall(MethodCall call, Result result) { + if (call.method.equals("allTestsFinished")) { + Map results = call.argument("results"); + testResultsSettable.set(results); + result.success(null); + } else { + result.notImplemented(); + } + } +} diff --git a/packages/integration_test/example/.gitignore b/packages/integration_test/example/.gitignore new file mode 100644 index 0000000000..2ddde2a5e3 --- /dev/null +++ b/packages/integration_test/example/.gitignore @@ -0,0 +1,73 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +**/doc/api/ +.dart_tool/ +.flutter-plugins +.packages +.pub-cache/ +.pub/ +/build/ + +# Android related +**/android/**/gradle-wrapper.jar +**/android/.gradle +**/android/captures/ +**/android/gradlew +**/android/gradlew.bat +**/android/local.properties +**/android/**/GeneratedPluginRegistrant.java + +# iOS/XCode related +**/ios/**/*.mode1v3 +**/ios/**/*.mode2v3 +**/ios/**/*.moved-aside +**/ios/**/*.pbxuser +**/ios/**/*.perspectivev3 +**/ios/**/*sync/ +**/ios/**/.sconsign.dblite +**/ios/**/.tags* +**/ios/**/.vagrant/ +**/ios/**/DerivedData/ +**/ios/**/Icon? +**/ios/**/Pods/ +**/ios/**/.symlinks/ +**/ios/**/profile +**/ios/**/xcuserdata +**/ios/.generated/ +**/ios/Flutter/App.framework +**/ios/Flutter/Flutter.framework +**/ios/Flutter/Generated.xcconfig +**/ios/Flutter/app.flx +**/ios/Flutter/app.zip +**/ios/Flutter/flutter_assets/ +**/ios/Flutter/flutter_export_environment.sh +**/ios/ServiceDefinitions.json +**/ios/Runner/GeneratedPluginRegistrant.* + +# Exceptions to above rules. +!**/ios/**/default.mode1v3 +!**/ios/**/default.mode2v3 +!**/ios/**/default.pbxuser +!**/ios/**/default.perspectivev3 +!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages diff --git a/packages/integration_test/example/README.md b/packages/integration_test/example/README.md new file mode 100644 index 0000000000..b5cc5d77e4 --- /dev/null +++ b/packages/integration_test/example/README.md @@ -0,0 +1,22 @@ +# integration_test_example + +Demonstrates how to use the `package:integration_test`. + +To run `integration_test/example_test.dart`, + +Android / iOS: + +```sh +flutter drive \ + --driver=test_driver/integration_test.dart \ + --target=integration_test/example_test.dart +``` + +Web: + +```sh +flutter drive \ + --driver=test_driver/integration_test.dart \ + --target=integration_test/example_test.dart \ + -d web-server +``` diff --git a/packages/integration_test/example/android/app/build.gradle b/packages/integration_test/example/android/app/build.gradle new file mode 100644 index 0000000000..bd9c7c4e90 --- /dev/null +++ b/packages/integration_test/example/android/app/build.gradle @@ -0,0 +1,65 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +def localProperties = new Properties() +def localPropertiesFile = rootProject.file('local.properties') +if (localPropertiesFile.exists()) { + localPropertiesFile.withReader('UTF-8') { reader -> + localProperties.load(reader) + } +} + +def flutterRoot = localProperties.getProperty('flutter.sdk') +if (flutterRoot == null) { + throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") +} + +def flutterVersionCode = localProperties.getProperty('flutter.versionCode') +if (flutterVersionCode == null) { + flutterVersionCode = '1' +} + +def flutterVersionName = localProperties.getProperty('flutter.versionName') +if (flutterVersionName == null) { + flutterVersionName = '1.0' +} + +apply plugin: 'com.android.application' +apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" + +android { + compileSdkVersion 29 + + lintOptions { + disable 'InvalidPackage' + } + + defaultConfig { + // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). + applicationId "com.example.integration_test_example" + minSdkVersion 16 + targetSdkVersion 28 + versionCode flutterVersionCode.toInteger() + versionName flutterVersionName + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + + buildTypes { + release { + // TODO: Add your own signing config for the release build. + // Signing with the debug keys for now, so `flutter run --release` works. + signingConfig signingConfigs.debug + } + } +} + +flutter { + source '../..' +} + +dependencies { + testImplementation 'junit:junit:4.12' + androidTestImplementation 'androidx.test:runner:1.2.0' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' +} diff --git a/packages/integration_test/example/android/app/src/androidTest/java/com/example/e2e_example/EmbedderV1ActivityTest.java b/packages/integration_test/example/android/app/src/androidTest/java/com/example/e2e_example/EmbedderV1ActivityTest.java new file mode 100644 index 0000000000..cf63d2f71d --- /dev/null +++ b/packages/integration_test/example/android/app/src/androidTest/java/com/example/e2e_example/EmbedderV1ActivityTest.java @@ -0,0 +1,17 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package com.example.integration_test_example; + +import androidx.test.rule.ActivityTestRule; +import dev.flutter.plugins.integration_test.FlutterTestRunner; +import org.junit.Rule; +import org.junit.runner.RunWith; + +@RunWith(FlutterTestRunner.class) +public class EmbedderV1ActivityTest { + @Rule + public ActivityTestRule rule = + new ActivityTestRule<>(EmbedderV1Activity.class, true, false); +} diff --git a/packages/integration_test/example/android/app/src/androidTest/java/com/example/e2e_example/FlutterActivityTest.java b/packages/integration_test/example/android/app/src/androidTest/java/com/example/e2e_example/FlutterActivityTest.java new file mode 100644 index 0000000000..6bac4a92f7 --- /dev/null +++ b/packages/integration_test/example/android/app/src/androidTest/java/com/example/e2e_example/FlutterActivityTest.java @@ -0,0 +1,18 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package com.example.integration_test_example; + +import androidx.test.rule.ActivityTestRule; +import dev.flutter.plugins.integration_test.FlutterTestRunner; +import io.flutter.embedding.android.FlutterActivity; +import org.junit.Rule; +import org.junit.runner.RunWith; + +@RunWith(FlutterTestRunner.class) +public class FlutterActivityTest { + @Rule + public ActivityTestRule rule = + new ActivityTestRule<>(FlutterActivity.class, true, false); +} diff --git a/packages/integration_test/example/android/app/src/androidTest/java/com/example/e2e_example/FlutterActivityWithPermissionTest.java b/packages/integration_test/example/android/app/src/androidTest/java/com/example/e2e_example/FlutterActivityWithPermissionTest.java new file mode 100644 index 0000000000..e3ed9effc5 --- /dev/null +++ b/packages/integration_test/example/android/app/src/androidTest/java/com/example/e2e_example/FlutterActivityWithPermissionTest.java @@ -0,0 +1,30 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package com.example.integration_test_example; + +import android.Manifest.permission; +import androidx.test.rule.ActivityTestRule; +import androidx.test.rule.GrantPermissionRule; +import dev.flutter.plugins.integration_test.FlutterTestRunner; +import io.flutter.embedding.android.FlutterActivity; +import org.junit.Rule; +import org.junit.runner.RunWith; + +/** + * Demonstrates how an integration test on Android can be run with permissions already granted. This + * is helpful if developers want to test native App behavior that depends on certain system service + * results which are guarded with permissions. + */ +@RunWith(FlutterTestRunner.class) +public class FlutterActivityWithPermissionTest { + + @Rule + public GrantPermissionRule permissionRule = + GrantPermissionRule.grant(permission.ACCESS_COARSE_LOCATION); + + @Rule + public ActivityTestRule rule = + new ActivityTestRule<>(FlutterActivity.class, true, false); +} diff --git a/packages/integration_test/example/android/app/src/debug/AndroidManifest.xml b/packages/integration_test/example/android/app/src/debug/AndroidManifest.xml new file mode 100644 index 0000000000..fa9a400b91 --- /dev/null +++ b/packages/integration_test/example/android/app/src/debug/AndroidManifest.xml @@ -0,0 +1,11 @@ + + + + + + diff --git a/packages/integration_test/example/android/app/src/main/AndroidManifest.xml b/packages/integration_test/example/android/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000000..189191cbe7 --- /dev/null +++ b/packages/integration_test/example/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + diff --git a/packages/integration_test/example/android/app/src/main/java/com/example/e2e_example/EmbedderV1Activity.java b/packages/integration_test/example/android/app/src/main/java/com/example/e2e_example/EmbedderV1Activity.java new file mode 100644 index 0000000000..6ad7ce60c0 --- /dev/null +++ b/packages/integration_test/example/android/app/src/main/java/com/example/e2e_example/EmbedderV1Activity.java @@ -0,0 +1,18 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package com.example.integration_test_example; + +import android.os.Bundle; +import dev.flutter.plugins.integration_test.IntegrationTestPlugin; +import io.flutter.app.FlutterActivity; + +public class EmbedderV1Activity extends FlutterActivity { + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + IntegrationTestPlugin.registerWith( + registrarFor("dev.flutter.plugins.integration_test.IntegrationTestPlugin")); + } +} diff --git a/packages/integration_test/example/android/app/src/main/res/drawable/launch_background.xml b/packages/integration_test/example/android/app/src/main/res/drawable/launch_background.xml new file mode 100644 index 0000000000..32d7798786 --- /dev/null +++ b/packages/integration_test/example/android/app/src/main/res/drawable/launch_background.xml @@ -0,0 +1,16 @@ + + + + + + + + + + diff --git a/packages/integration_test/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/packages/integration_test/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..db77bb4b7b0906d62b1847e87f15cdcacf6a4f29 GIT binary patch literal 544 zcmeAS@N?(olHy`uVBq!ia0y~yVDJE84rT@hh9qO>QU(SF$r9IylHmNblJdl&R0hYC z{G?O`&)mfH)S%SFl*+=BsWuD@4C?}XLR=Xb7#RJ!7{h04Zu=H;^aq4w44VZJaXaum zG@>0o`I5 z6U6gpN>(hBs@ovlyiK}omrVN}&28UY_JdsVcA=Cl0|SF_NswPKgMfg5KtMnO2sE4r zf%}pIPku2lFue41aSVw#{PxUsz9t6&hrp0GdlTMw^~h@f`fs1s!olsWbZ#C0v7PJ9 zExVjNeb(Ol`RU07XFf|X@qSK7qke0_C&kUH>MnD(8u-mi5B zt(&|xZ@%@sBNk%nt_5+E&U1QAlyT>>sMB2Zd5T5*R3&Sld5=98o%0qdm+@@-JjKB8 z(xcUiGOB?O=e)LCdt!o~wXBiQlFwyn4J{(JaZG%Q-e|yQz{EjrrIztFmwg@gt#&=FffMC4mtWmbKAF&qdyqKXG0ipk&vT5 zAmZ%d{SXF=bCKq@Z-GZZ;tV#~j83JDzFmxd-Hahq8AGNqhE8V;o5>h9i!po_WB6=l zU2kT?Kvt(bR^JA;;7+;DUGlvL6sMk6nsrHO&Q;BA-wby`jSBSdXJueu5G@Jv3uX`y zP*5;1FzBB@fBpXR=g+?ff&5MV!VC-yOFdm2Lp+YZy>e2h$w0vMVh8iNMNLhM)++IJ z{QqCg*LgRGXKpKZaOLSMJFo8MNc{figWv3mbJp+w-BoBm(|-hT|4dcbJ2lEyX!??Y`jpZ81*D{;rF6b`?;0>>pbJRKPRw2)?8wK8GH9> zL)n=k&vkA#ITl(SSsBW`??>AG{pM|AK2Jc#t6>y4N#$)H8ZEGkUc!`m{6pbTImMF#2{f z`gJk-_b~?aGX_m$44TXsJQ-wH$W+GA>5O4B7{g{VhRtFOpT!tHo5?tW$tsn}K99+{ zjLE&4*|Uz>tC88eNi3sZJbQ{n(LBkDd1t=Sn-plsE283-d*czTa-zm@iQD#kujt@|Kvt4hp|H z71QJA-@DE-vCc=}m3vdfeqD}l&W>B;IduNM%M_}RPx;yPVrk2E_T?&?d+vqXsA}xF zGk52_Ny78;-$vOoENNLjTll#WOG?YLuZ?eO;uVxk)@?h*_~6>qo(~l}_f@BaD>p=c zm>yaWRpaQm|`^KGX?!;c=*_;KycpYksb1 rdBk${xlomwC<})`ozHbP0l+XkKcl<5t literal 0 HcmV?d00001 diff --git a/packages/integration_test/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/packages/integration_test/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..d5f1c8d34e7a88e3f88bea192c3a370d44689c3c GIT binary patch literal 1031 zcmeAS@N?(olHy`uVBq!ia0y~yV3+{H9Lx+13>Rhybuln7NS3%plmzFem6RtIr7}3C z$Dctjh(SM?K|h4SAdJB{hQT_6!9JhSFr3jep3y9U z(L9OKDxJ|flhG!d(I$t{HiywRm(ebd(Y}z;v6#`Zgwd&#(Yb=rrHawDn$fL>(XE!z zt&Y*Xj?trm(W8;kvysuWiP5u}(X)lotC`WOh0&*-(Wisaw}a8QlhLo6(XWTmzlYJk zmocD^F|eO8Z~|lCM8?2Lj6o9_gC>F8A3T{ccnV|4RK}2LjG@yRLuW9C&0q|h$rv_^ zF?<$d_-uBwU=HgjPRC?Uw`?x2A}+rQ?!a2^kVfvX7VhwN?#NE=s4niP9-inPl?69d z7T#1{bVqf`J=LWT)RsR~Tk%+JQT9|ZQFKYxDR#LKT37?|`uT^vIyZoR#b9vmDf()v(?iz7_L)oF78 zkJJ<)r8pUt8M$!5-N#*39u$gn zR>-(G$wg0`aolam=a?PG9$oC(GH>-!X0d*^l*gJvuFJp95x7~EvFLL3EEhhxt`pq; z%_lBC*86lUSiR`uj?O)w{s`}^n&Wz}@?RH+ochG+^SU~oY!t72t=ZWjXFc({Ty9i< zoXX3Kohi2Ju9xPeP296QFr{gETuR&Xh?K77YDUL{MQ1+I?2fS6ciP3jaR24wmqlki zKfgU-wdbO}>o1>vX;$n~9ltDoY4ItEi|?MFbkSNqMRUkMU-}~Bs z)+NdNzgg`VE)XKX=tVT|2z5{L4{YJjHWS*rIm-E6Ws`IFvdRnm87H fR&jd1QhDAN-h`R^uRUjAU|{fc^>bP0l+XkKAv&s= literal 0 HcmV?d00001 diff --git a/packages/integration_test/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/packages/integration_test/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..4d6372eebdb28e45604e46eeda8dd24651419bc0 GIT binary patch literal 1443 zcmeAS@N?(olHy`uVBq!ia0y~yU^oE69Lx+145>_WOc@v$BuiW)N`mv#O3D+9QW+dm z@{>{(JaZG%Q-e|yQz{EjrrIztFy0FA32|j$U7=vLLgJC#>aTJ4T9D`W`gLwjjbtZ#N4x^eAqnb0LmM5cOIHO54qe%>- zNi3sjJfm3xqeU{KMGB*38lzP@qg4i@bta=t7NczrqirsuT`r?t9;018qkTT3eF39G z5u;-~4uK+6lW`UY0|SF-NswPKgMfko7&thbzyBTz-gcI+Wnf^o^K@|x zskrs_3VX0{ph#Pyi^G})N%|2R%{L?-ZV(U%Y+lqcfu(WAio}U)uIrV(+3WUaecD+A zmQ6SJem|Gdo_Kp z-*x@+`J3Y19B#kQTkx(t_`-K<>p6dn#rh_GuokuWC9d+nXX1zFdIcZVw{qEhc&=6O z^|eUFqwV?=KCBk6c(Pr4!l%_@70=G=P581}wBp75D22D-njfy%?{qk*AOB#Z{bq-g z`q2+|)-Q6ns2@Io{eMN{rubzF`u|EA+wSjG@UL6#aQc1N1oQe;4(H#;OmN?SS>~@F ztIeOC+&g|0i+=ccTfE@YZP5>((!~ot`|Cb zb^PFdrt-VXypJEaJ95?T2$v)Ws{O#V4Ednvz`|Pb} zf4VOe!@bWom-}e`tT2YtP3!%mny=z+}-K6mV2ZEt5Icwo(g z%Zr!wX>UAuh9QhqUj7<;)5IBxDQpH>KRz6|eoM6P*rQ_`EdPlXYgN?$U-3W2|NYf9 z3~H?J-^u1!lq%j3KgpL6_~F~TxcJXA&m~w0?N0Rh)m167XXobE9?sqiHmlnth&$|i z@b&H6->;epMCgPeb()B(Tr|RH~O+1PwlVxdT!ROU2OGQ3PvhLeQAwP zO|AMWqpQ}lM;-?Ix_3Z(ZoZK*%HiZ|EUDeVf^rGH<21r@EM zSf|zZ`p5aNP1ut4@|gFs0GYW>Kcl68^QPJ_Y + + + + + diff --git a/packages/integration_test/example/android/app/src/profile/AndroidManifest.xml b/packages/integration_test/example/android/app/src/profile/AndroidManifest.xml new file mode 100644 index 0000000000..fa9a400b91 --- /dev/null +++ b/packages/integration_test/example/android/app/src/profile/AndroidManifest.xml @@ -0,0 +1,11 @@ + + + + + + diff --git a/packages/integration_test/example/android/build.gradle b/packages/integration_test/example/android/build.gradle new file mode 100644 index 0000000000..3605b5c5f3 --- /dev/null +++ b/packages/integration_test/example/android/build.gradle @@ -0,0 +1,33 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +buildscript { + repositories { + google() + jcenter() + } + + dependencies { + classpath 'com.android.tools.build:gradle:3.6.3' + } +} + +allprojects { + repositories { + google() + jcenter() + } +} + +rootProject.buildDir = '../build' +subprojects { + project.buildDir = "${rootProject.buildDir}/${project.name}" +} +subprojects { + project.evaluationDependsOn(':app') +} + +task clean(type: Delete) { + delete rootProject.buildDir +} diff --git a/packages/integration_test/example/android/gradle.properties b/packages/integration_test/example/android/gradle.properties new file mode 100644 index 0000000000..755300e3a0 --- /dev/null +++ b/packages/integration_test/example/android/gradle.properties @@ -0,0 +1,4 @@ +org.gradle.jvmargs=-Xmx1536M + +android.useAndroidX=true +android.enableJetifier=true diff --git a/packages/integration_test/example/android/gradle/wrapper/gradle-wrapper.properties b/packages/integration_test/example/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000000..bc24dcf039 --- /dev/null +++ b/packages/integration_test/example/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Fri Jun 23 08:50:38 CEST 2017 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip diff --git a/packages/integration_test/example/android/settings.gradle b/packages/integration_test/example/android/settings.gradle new file mode 100644 index 0000000000..bef552ed4c --- /dev/null +++ b/packages/integration_test/example/android/settings.gradle @@ -0,0 +1,19 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +include ':app' + +def flutterProjectRoot = rootProject.projectDir.parentFile.toPath() + +def plugins = new Properties() +def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins') +if (pluginsFile.exists()) { + pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) } +} + +plugins.each { name, path -> + def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile() + include ":$name" + project(":$name").projectDir = pluginDirectory +} diff --git a/packages/integration_test/example/integration_test/_example_test_io.dart b/packages/integration_test/example/integration_test/_example_test_io.dart new file mode 100644 index 0000000000..07f604e0be --- /dev/null +++ b/packages/integration_test/example/integration_test/_example_test_io.dart @@ -0,0 +1,45 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// This is a basic Flutter widget test. +// +// To perform an interaction with a widget in your test, use the WidgetTester +// utility that Flutter provides. For example, you can send tap and scroll +// gestures. You can also use WidgetTester to find child widgets in the widget +// tree, read text, and verify that the values of widget properties are correct. + +import 'dart:io' show Platform; +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:integration_test/integration_test.dart'; + +import 'package:integration_test_example/main.dart' as app; + +void main() { + final IntegrationTestWidgetsFlutterBinding binding = + IntegrationTestWidgetsFlutterBinding.ensureInitialized() + as IntegrationTestWidgetsFlutterBinding; + testWidgets('verify text', (WidgetTester tester) async { + // Build our app and trigger a frame. + app.main(); + + // Trace the timeline of the following operation. The timeline result will + // be written to `build/integration_response_data.json` with the key + // `timeline`. + await binding.traceAction(() async { + // Trigger a frame. + await tester.pumpAndSettle(); + + // Verify that platform version is retrieved. + expect( + find.byWidgetPredicate( + (Widget widget) => + widget is Text && + widget.data.startsWith('Platform: ${Platform.operatingSystem}'), + ), + findsOneWidget, + ); + }); + }); +} diff --git a/packages/integration_test/example/integration_test/_example_test_web.dart b/packages/integration_test/example/integration_test/_example_test_web.dart new file mode 100644 index 0000000000..cd5e986ded --- /dev/null +++ b/packages/integration_test/example/integration_test/_example_test_web.dart @@ -0,0 +1,39 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// This is a basic Flutter widget test. +// +// To perform an interaction with a widget in your test, use the WidgetTester +// utility that Flutter provides. For example, you can send tap and scroll +// gestures. You can also use WidgetTester to find child widgets in the widget +// tree, read text, and verify that the values of widget properties are correct. + +import 'dart:html' as html; +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:integration_test/integration_test.dart'; + +import 'package:integration_test_example/main.dart' as app; + +void main() { + IntegrationTestWidgetsFlutterBinding.ensureInitialized(); + testWidgets('verify text', (WidgetTester tester) async { + // Build our app and trigger a frame. + app.main(); + + // Trigger a frame. + await tester.pumpAndSettle(); + + // Verify that platform is retrieved. + expect( + find.byWidgetPredicate( + (Widget widget) => + widget is Text && + widget.data + .startsWith('Platform: ${html.window.navigator.platform}\n'), + ), + findsOneWidget, + ); + }); +} diff --git a/packages/integration_test/example/integration_test/_extended_test_io.dart b/packages/integration_test/example/integration_test/_extended_test_io.dart new file mode 100644 index 0000000000..f67c94ab4e --- /dev/null +++ b/packages/integration_test/example/integration_test/_extended_test_io.dart @@ -0,0 +1,42 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// This is a basic Flutter widget test. +// +// To perform an interaction with a widget in your test, use the WidgetTester +// utility that Flutter provides. For example, you can send tap and scroll +// gestures. You can also use WidgetTester to find child widgets in the widget +// tree, read text, and verify that the values of widget properties are correct. + +import 'dart:io' show Platform; +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:integration_test/integration_test.dart'; + +import 'package:integration_test_example/main.dart' as app; + +void main() { + IntegrationTestWidgetsFlutterBinding.ensureInitialized(); + + testWidgets('verify text', (WidgetTester tester) async { + // Build our app and trigger a frame. + app.main(); + + // Trigger a frame. + await tester.pumpAndSettle(); + + // TODO(nturgut): https://github.com/flutter/flutter/issues/51890 + // Add screenshot capability for mobile platforms. + + // Verify that platform version is retrieved. + expect( + find.byWidgetPredicate( + (Widget widget) => + widget is Text && + widget.data.startsWith('Platform: ${Platform.operatingSystem}'), + ), + findsOneWidget, + ); + }); +} diff --git a/packages/integration_test/example/integration_test/_extended_test_web.dart b/packages/integration_test/example/integration_test/_extended_test_web.dart new file mode 100644 index 0000000000..8dd6a3d24c --- /dev/null +++ b/packages/integration_test/example/integration_test/_extended_test_web.dart @@ -0,0 +1,55 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// This is a basic Flutter widget test. +// +// To perform an interaction with a widget in your test, use the WidgetTester +// utility that Flutter provides. For example, you can send tap and scroll +// gestures. You can also use WidgetTester to find child widgets in the widget +// tree, read text, and verify that the values of widget properties are correct. + +import 'dart:html' as html; +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:integration_test/integration_test.dart'; + +import 'package:integration_test_example/main.dart' as app; + +void main() { + final IntegrationTestWidgetsFlutterBinding binding = IntegrationTestWidgetsFlutterBinding.ensureInitialized() as IntegrationTestWidgetsFlutterBinding; + + testWidgets('verify text', (WidgetTester tester) async { + // Build our app and trigger a frame. + app.main(); + + // Trigger a frame. + await tester.pumpAndSettle(); + + // Take a screenshot. + await binding.takeScreenshot('platform_name'); + + // Verify that platform is retrieved. + expect( + find.byWidgetPredicate( + (Widget widget) => + widget is Text && + widget.data + .startsWith('Platform: ${html.window.navigator.platform}\n'), + ), + findsOneWidget, + ); + }); + + testWidgets('verify screenshot', (WidgetTester tester) async { + // Build our app and trigger a frame. + app.main(); + + // Trigger a frame. + await tester.pumpAndSettle(); + + // Multiple methods can take screenshots. Screenshots are taken with the + // same order the methods run. + await binding.takeScreenshot('platform_name_2'); + }); +} diff --git a/packages/integration_test/example/integration_test/example_test.dart b/packages/integration_test/example/integration_test/example_test.dart new file mode 100644 index 0000000000..8a9c97701f --- /dev/null +++ b/packages/integration_test/example/integration_test/example_test.dart @@ -0,0 +1,20 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// This is a basic Flutter widget test. +// +// To perform an interaction with a widget in your test, use the WidgetTester +// utility that Flutter provides. For example, you can send tap and scroll +// gestures. You can also use WidgetTester to find child widgets in the widget +// tree, read text, and verify that the values of widget properties are correct. + +import 'package:integration_test/integration_test.dart'; + +import '_example_test_io.dart' if (dart.library.html) '_example_test_web.dart' + as tests; + +void main() { + IntegrationTestWidgetsFlutterBinding.ensureInitialized(); + tests.main(); +} diff --git a/packages/integration_test/example/integration_test/extended_test.dart b/packages/integration_test/example/integration_test/extended_test.dart new file mode 100644 index 0000000000..d43296dd1b --- /dev/null +++ b/packages/integration_test/example/integration_test/extended_test.dart @@ -0,0 +1,23 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// This is a Flutter widget test can take a screenshot. +// +// NOTE: Screenshots are only supported on Web for now. For Web, this needs to +// be executed with the `test_driver/integration_test_extended_driver.dart`. +// +// To perform an interaction with a widget in your test, use the WidgetTester +// utility that Flutter provides. For example, you can send tap and scroll +// gestures. You can also use WidgetTester to find child widgets in the widget +// tree, read text, and verify that the values of widget properties are correct. + +import 'package:integration_test/integration_test.dart'; + +import '_extended_test_io.dart' if (dart.library.html) '_extended_test_web.dart' + as tests; + +void main() { + IntegrationTestWidgetsFlutterBinding.ensureInitialized(); + tests.main(); +} diff --git a/packages/integration_test/example/ios/Flutter/AppFrameworkInfo.plist b/packages/integration_test/example/ios/Flutter/AppFrameworkInfo.plist new file mode 100644 index 0000000000..6b4c0f78a7 --- /dev/null +++ b/packages/integration_test/example/ios/Flutter/AppFrameworkInfo.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + App + CFBundleIdentifier + io.flutter.flutter.app + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + App + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + MinimumOSVersion + 8.0 + + diff --git a/packages/integration_test/example/ios/Flutter/Debug.xcconfig b/packages/integration_test/example/ios/Flutter/Debug.xcconfig new file mode 100644 index 0000000000..e8efba1146 --- /dev/null +++ b/packages/integration_test/example/ios/Flutter/Debug.xcconfig @@ -0,0 +1,2 @@ +#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" +#include "Generated.xcconfig" diff --git a/packages/integration_test/example/ios/Flutter/Release.xcconfig b/packages/integration_test/example/ios/Flutter/Release.xcconfig new file mode 100644 index 0000000000..399e9340e6 --- /dev/null +++ b/packages/integration_test/example/ios/Flutter/Release.xcconfig @@ -0,0 +1,2 @@ +#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" +#include "Generated.xcconfig" diff --git a/packages/integration_test/example/ios/Podfile b/packages/integration_test/example/ios/Podfile new file mode 100644 index 0000000000..f7d6a5e68c --- /dev/null +++ b/packages/integration_test/example/ios/Podfile @@ -0,0 +1,38 @@ +# Uncomment this line to define a global platform for your project +# platform :ios, '9.0' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) + unless File.exist?(generated_xcode_build_settings_path) + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" + end + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches + end + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" +end + +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_ios_podfile_setup + +target 'Runner' do + flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + flutter_additional_ios_build_settings(target) + end +end diff --git a/packages/integration_test/example/ios/Runner.xcodeproj/project.pbxproj b/packages/integration_test/example/ios/Runner.xcodeproj/project.pbxproj new file mode 100644 index 0000000000..b96fa2fb26 --- /dev/null +++ b/packages/integration_test/example/ios/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,733 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; }; + 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 769541CB23A0351900E5C350 /* RunnerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 769541CA23A0351900E5C350 /* RunnerTests.m */; }; + 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; }; + 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */; }; + 97C146F31CF9000F007C117D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 97C146F21CF9000F007C117D /* main.m */; }; + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; + C2A5EDF11F4FDBF3ABFD7006 /* libPods-Runner.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 625A5A90428602E25C0DE2F6 /* libPods-Runner.a */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 769541CD23A0351900E5C350 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 97C146E61CF9000F007C117D /* Project object */; + proxyType = 1; + remoteGlobalIDString = 97C146ED1CF9000F007C117D; + remoteInfo = Runner; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 9705A1C41CF9048500538489 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */, + 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 0D6F1CB5DBBEBCC75AFAD041 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = ""; }; + 625A5A90428602E25C0DE2F6 /* libPods-Runner.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Runner.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 769541BF23A0337200E5C350 /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Platforms/iPhoneOS.platform/Developer/Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; + 769541C823A0351900E5C350 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 769541CA23A0351900E5C350 /* RunnerTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RunnerTests.m; sourceTree = ""; }; + 769541CC23A0351900E5C350 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; + 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; + 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; + 9740EEBA1CF902C7004384FC /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; sourceTree = ""; }; + 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 97C146F21CF9000F007C117D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + D69CCAD5F82E76E2E22BFA96 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + E23EF4D45DAE46B9DDB9B445 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 769541C523A0351900E5C350 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 97C146EB1CF9000F007C117D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */, + 3B80C3941E831B6300D905FE /* App.framework in Frameworks */, + C2A5EDF11F4FDBF3ABFD7006 /* libPods-Runner.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 42D734D13B733A64B01A24A9 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 769541BF23A0337200E5C350 /* XCTest.framework */, + 625A5A90428602E25C0DE2F6 /* libPods-Runner.a */, + ); + name = Frameworks; + sourceTree = ""; + }; + 769541C923A0351900E5C350 /* RunnerTests */ = { + isa = PBXGroup; + children = ( + 769541CA23A0351900E5C350 /* RunnerTests.m */, + 769541CC23A0351900E5C350 /* Info.plist */, + ); + path = RunnerTests; + sourceTree = ""; + }; + 9740EEB11CF90186004384FC /* Flutter */ = { + isa = PBXGroup; + children = ( + 3B80C3931E831B6300D905FE /* App.framework */, + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, + 9740EEBA1CF902C7004384FC /* Flutter.framework */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 9740EEB31CF90195004384FC /* Generated.xcconfig */, + ); + name = Flutter; + sourceTree = ""; + }; + 97C146E51CF9000F007C117D = { + isa = PBXGroup; + children = ( + 9740EEB11CF90186004384FC /* Flutter */, + 97C146F01CF9000F007C117D /* Runner */, + 769541C923A0351900E5C350 /* RunnerTests */, + 97C146EF1CF9000F007C117D /* Products */, + BAB55133DD7BD81A2557E916 /* Pods */, + 42D734D13B733A64B01A24A9 /* Frameworks */, + ); + sourceTree = ""; + }; + 97C146EF1CF9000F007C117D /* Products */ = { + isa = PBXGroup; + children = ( + 97C146EE1CF9000F007C117D /* Runner.app */, + 769541C823A0351900E5C350 /* RunnerTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 97C146F01CF9000F007C117D /* Runner */ = { + isa = PBXGroup; + children = ( + 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */, + 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */, + 97C146FA1CF9000F007C117D /* Main.storyboard */, + 97C146FD1CF9000F007C117D /* Assets.xcassets */, + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, + 97C147021CF9000F007C117D /* Info.plist */, + 97C146F11CF9000F007C117D /* Supporting Files */, + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, + ); + path = Runner; + sourceTree = ""; + }; + 97C146F11CF9000F007C117D /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 97C146F21CF9000F007C117D /* main.m */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + BAB55133DD7BD81A2557E916 /* Pods */ = { + isa = PBXGroup; + children = ( + D69CCAD5F82E76E2E22BFA96 /* Pods-Runner.debug.xcconfig */, + 0D6F1CB5DBBEBCC75AFAD041 /* Pods-Runner.release.xcconfig */, + E23EF4D45DAE46B9DDB9B445 /* Pods-Runner.profile.xcconfig */, + ); + path = Pods; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 769541C723A0351900E5C350 /* RunnerTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 769541CF23A0351900E5C350 /* Build configuration list for PBXNativeTarget "RunnerTests" */; + buildPhases = ( + 769541C423A0351900E5C350 /* Sources */, + 769541C523A0351900E5C350 /* Frameworks */, + 769541C623A0351900E5C350 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 769541CE23A0351900E5C350 /* PBXTargetDependency */, + ); + name = RunnerTests; + productName = RunnerTests; + productReference = 769541C823A0351900E5C350 /* RunnerTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 97C146ED1CF9000F007C117D /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + 2882CCC16181B61F1ABC876C /* [CP] Check Pods Manifest.lock */, + 9740EEB61CF901F6004384FC /* Run Script */, + 97C146EA1CF9000F007C117D /* Sources */, + 97C146EB1CF9000F007C117D /* Frameworks */, + 97C146EC1CF9000F007C117D /* Resources */, + 9705A1C41CF9048500538489 /* Embed Frameworks */, + 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + 0D321280D358770769172C49 /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Runner; + productName = Runner; + productReference = 97C146EE1CF9000F007C117D /* Runner.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 97C146E61CF9000F007C117D /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 1020; + ORGANIZATIONNAME = "The Chromium Authors"; + TargetAttributes = { + 769541C723A0351900E5C350 = { + CreatedOnToolsVersion = 11.0; + ProvisioningStyle = Automatic; + TestTargetID = 97C146ED1CF9000F007C117D; + }; + 97C146ED1CF9000F007C117D = { + CreatedOnToolsVersion = 7.3.1; + }; + }; + }; + buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 97C146E51CF9000F007C117D; + productRefGroup = 97C146EF1CF9000F007C117D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 97C146ED1CF9000F007C117D /* Runner */, + 769541C723A0351900E5C350 /* RunnerTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 769541C623A0351900E5C350 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 97C146EC1CF9000F007C117D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 0D321280D358770769172C49 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "[CP] Embed Pods Frameworks"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + 2882CCC16181B61F1ABC876C /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Thin Binary"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" thin"; + }; + 9740EEB61CF901F6004384FC /* Run Script */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Run Script"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 769541C423A0351900E5C350 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 769541CB23A0351900E5C350 /* RunnerTests.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 97C146EA1CF9000F007C117D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */, + 97C146F31CF9000F007C117D /* main.m in Sources */, + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 769541CE23A0351900E5C350 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 97C146ED1CF9000F007C117D /* Runner */; + targetProxy = 769541CD23A0351900E5C350 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 97C146FA1CF9000F007C117D /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C146FB1CF9000F007C117D /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C147001CF9000F007C117D /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 249021D3217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Profile; + }; + 249021D4217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.instrumentationAdapterExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Profile; + }; + 769541D023A0351900E5C350 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_STYLE = Automatic; + GCC_C_LANGUAGE_STANDARD = gnu11; + INFOPLIST_FILE = RunnerTests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = com.example.instrumentationAdapterExample.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/Runner"; + }; + name = Debug; + }; + 769541D123A0351900E5C350 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_STYLE = Automatic; + GCC_C_LANGUAGE_STANDARD = gnu11; + INFOPLIST_FILE = RunnerTests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = com.example.instrumentationAdapterExample.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/Runner"; + }; + name = Release; + }; + 769541D223A0351900E5C350 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_STYLE = Automatic; + GCC_C_LANGUAGE_STANDARD = gnu11; + INFOPLIST_FILE = RunnerTests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = com.example.instrumentationAdapterExample.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/Runner"; + }; + name = Profile; + }; + 97C147031CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 97C147041CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 97C147061CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.instrumentationAdapterExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Debug; + }; + 97C147071CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.instrumentationAdapterExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 769541CF23A0351900E5C350 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 769541D023A0351900E5C350 /* Debug */, + 769541D123A0351900E5C350 /* Release */, + 769541D223A0351900E5C350 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147031CF9000F007C117D /* Debug */, + 97C147041CF9000F007C117D /* Release */, + 249021D3217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147061CF9000F007C117D /* Debug */, + 97C147071CF9000F007C117D /* Release */, + 249021D4217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 97C146E61CF9000F007C117D /* Project object */; +} diff --git a/packages/integration_test/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/packages/integration_test/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 0000000000..72fa1469f5 --- /dev/null +++ b/packages/integration_test/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,97 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/integration_test/example/ios/Runner/AppDelegate.h b/packages/integration_test/example/ios/Runner/AppDelegate.h new file mode 100644 index 0000000000..7d5bcd37fc --- /dev/null +++ b/packages/integration_test/example/ios/Runner/AppDelegate.h @@ -0,0 +1,10 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import +#import + +@interface AppDelegate : FlutterAppDelegate + +@end diff --git a/packages/integration_test/example/ios/Runner/AppDelegate.m b/packages/integration_test/example/ios/Runner/AppDelegate.m new file mode 100644 index 0000000000..50f10d0d53 --- /dev/null +++ b/packages/integration_test/example/ios/Runner/AppDelegate.m @@ -0,0 +1,17 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "AppDelegate.h" +#include "GeneratedPluginRegistrant.h" + +@implementation AppDelegate + +- (BOOL)application:(UIApplication *)application + didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + [GeneratedPluginRegistrant registerWithRegistry:self]; + // Override point for customization after application launch. + return [super application:application didFinishLaunchingWithOptions:launchOptions]; +} + +@end diff --git a/packages/integration_test/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/packages/integration_test/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000000..d36b1fab2d --- /dev/null +++ b/packages/integration_test/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,122 @@ +{ + "images" : [ + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@3x.png", + "scale" : "3x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@3x.png", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@3x.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@2x.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@3x.png", + "scale" : "3x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@1x.png", + "scale" : "1x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@1x.png", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@1x.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@2x.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "Icon-App-83.5x83.5@2x.png", + "scale" : "2x" + }, + { + "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "Icon-App-1024x1024@1x.png", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/packages/integration_test/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/packages/integration_test/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..dc9ada4725e9b0ddb1deab583e5b5102493aa332 GIT binary patch literal 10932 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 QlAxuUp00i_>zopr0K8b=b^rhX literal 0 HcmV?d00001 diff --git a/packages/integration_test/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/packages/integration_test/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..28c6bf03016f6c994b70f38d1b7346e5831b531f GIT binary patch literal 564 zcmeAS@N?(olHy`uVBq!ia0y~yU=RUe4mJh`hTcwDUIqpR#^NA%Cx&(BWL`2bFuwD2 zaSX8#TsvjAw@jeOvGY5>_q|>h+1u6fBdexi<)tM8-3iJOH-6e{csS^|t`^`h%M4z^ zvrUsp%yCUni-1dr!HteCeu1-6sf(@4&z-gOX8TrnJhnM~hPD2_`!&xEoBNpM46ZP5 z>RM6Fs4Du%wQt&V4?nF#Au;N4dCxlREhFOs+Q*8UNIXwA$#oIyO8|+tqV&R#9*$ zUnSd|Hw&5HJe-|^3yuFWnr2?uxcNuK(*U^*-n;k6AAGamV&=3x zQTjVJM+cmBEL?H-jDy2s*;QO>QThRLANE|lxz@Sy?+%4F#V^}4%*``0mhkR1xTsnd zsl4K{bVpgeu!#g~y%YEC?D&;me>Lr&{KSK$>&ee#llSpUG=!hMOnEB&rtbEo$NBpo ze0#XwfU{CPz~%7UQ+uQ}ChR*S%%W*wac<_u>)Jc^mA`9MySCxd!B^Kd#zy?>WBq3t zA?x*4_ W$LnK$#EXG}fx*+&&t;ucLK6TGg!*^@ literal 0 HcmV?d00001 diff --git a/packages/integration_test/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/packages/integration_test/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..2ccbfd967d9697cd4b83225558af2911e9571c9b GIT binary patch literal 1283 zcmeAS@N?(olHy`uVBq!ia0y~yV9)?z4mJh`hMs>rav2y{PIR?dBvs;g z{d;TUyFpPJ%eF4Kv7n|^zp=ULn1t;EM$XP7lUeld*iOAGhrAO=?vmAmpTR*XMV$8#$?-Y`cDL-1XCS@pJejB8Rvppy6eq7etCUAujg?qj6J!e{Uv#AAYb{|~a_aH522J@Q@fi&BOpfuWHHbGp zf5x@0=W&%z;t#%xYZ_i1#tsY?XV=JR1*ru$Xe%q8GYMi`*I43cb15zIa$ef*g)OP` zxn+8uo27Eb>{9r}R#PV@sJksCu`zk^$I#qqi)ZJWE@$GC^4#7iY9ct-)8d8n31bVb zX;lK#VjdrPy!sZ;@og0)Rhw5$KOp&F-NcXuofoDxM?Z25Q1Tbd+xYNCT0eV~Php(s zr(KmiUp+T6+&?C9dbVk>SLWbgX@7~0v#&fvx}_S)%a@u$R+v$Lgb zcLiOYf4R$3h^y$~8P-z=e?C;X^D^2|@K|_BOOua4qui|r8!K13nyLg|73lxrZXr*ju;F zgx|erIDfsIxhjhHXMvIP?8enx7P6mu>*fc1c=y;ahGSjp;lGuBcQh{SzH#ApT49dK z`Ang8Y6pT&Jlr#3(Hn0W*>~S9f3}}*)^yfuapkkQmiJL7h52FRWrLWr4F+59@QKX* z&iiA|j)#}$b~)uf+UVL>vE{JpQwhGc;jIHlKqXlCF80s&R_HEmS6Euygc@5k7ASXhVP2g(|73{u6(F=?yx`%zx0!xh0k=> z@2~H(ejI6YT%e^_^d0ZiKSyPK{bY7bNiOgy*`?Sx*{Rj0zP_&O%zjCcZ5wK1&7b$b zS-4u+Re)>xxmODx+IoKSah(vkF4bmQOJ?4@n*L71#9h^eYmdsG-&9-ce|Um#?yRl} zHz)kP-&6SUG5^IIEML~BMqVrRQjA}+dhu305AQAA`6pzU9W{1E>(0+>-l`ogtQT#4 zv{I4dqgB+-Pp<{^Wvq|eKaP}%{%owt&7)o~)wHF}A<4B|UA%w)kz-Te{&=aQJFhvL zcU`h$Qee7tc-{WP?;gh+O*;8F!nyTEd4_zXS=)6n^)GSALu(@ zFj_mOP`4*Na%-LC^ZU2XzIy6y&|qkMNLIl0d(*@(Mjs@LFW7h~w7dO(eCMgX;W}ey z)$1FVT(;b{_T{serM4|X+iVsv?@3bGd0_hizGsX6s!a`EBIo^}j%A+F$3@YdzmBZj z*|cUF%e7fvr+yyrOFrYjRQJK&Nt+6#ztwGP_&n*`Q6J-9SNuJG)iEwe+w485%%@SC z)0^p~ht+}=x9!*b3^nYjoiqK*szo(3n7-R@emEuiR&Q1|0|Nttr>mdKI;Vst04OMA Ap8x;= literal 0 HcmV?d00001 diff --git a/packages/integration_test/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/packages/integration_test/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..f091b6b0bca859a3f474b03065bef75ba58a9e4c GIT binary patch literal 1588 zcmeAS@N?(olHy`uVBq!ia0y~yV6XvU4mJh`2CF|eix?PKe|x$(hGg8kJ3Br{#8u|_ z_r9dgjs8-qSv*|RE-Crj{anx)sHw2EzMm;qaVooM=);5T@;xrShAOR6jo*@1hGhwO z*Bn?RA+_;(9Jkc0h_1C6OiM+)8lAkW@7{ZN=luOQXSY;ezx(#?+xhn_PnvIj`}XeJ z^!>*B=l;CgqmUuO5V6FnP9n7P7vI(PUCpz+gzmb2UA)izt%L5>BmwRAzjvSyiSyI*IpJk#T4b1F!2XiIK3GC99kKERz# z#llXd+2zr$^&!bCj%$9Ht@T@0)2LZ?29M*>nVA(Yw`)dRH)Gvt71bSeUv1N8mlwNS z4~cv<&5bGxdhmFUwk2P6nbfCSt~c(e9$MyCd+~brAEhae3h!HZF0uY#ctl^M;=oEh z(YHFSOC65Z)mDD^`iD=@>%)&j5}iNhupByS+SuzUe&ptiL~GxJZZT~WzMM zs3oO+Z-U~Qw+BwLWovJkY4`eL^zEKpb~Dihf4*5{OBWa&j^dNy)Yi)|*(PgYMMC%(TgB=f_)>F?(i-{Lt}{cgTc64|8SnG>gdgv-0M z(1s<|VnxMTTb{`)Ht(^kpRVzIUFuFP+oy}nez;V8{4%BJUwpF4!=7ZH11hhWxUG8{ zA2;g0;CQ~u#_FdI|LM$&=U4x!m1<*B4F0*|#%z<{ZT|`v#dz%F+j3FFpSx_|G^hRD zW%J)k7_+H6FI!yg@DykaiKnaiTRan`fRnej^uRO`~` zZcTY`aN)}6R;!CM4$pJE5o*tx@U-)Q&jsxwiEEP794E+$s2TE$tVcc1Hf{mdn7 z8>DtsPdQ-Bv3rs0ZqMKwZ-R|d*iW(@%W-2Az}rFP|(+}bujN=5dCfllL@XNex?Z}U36Q-AR7O5^Gy z+?mm@1b6B25oJSg3m9 zMild*)AOC8jwTjNm7B#Z%@~`p_p(StiPChHi3NR!uAB2nKJDc?v*_&CT?fn@g}G`% zlc!`Tn<#uKJ+Z*R_1=vIXU+4^nK?E3H#MK0_T%Wb@BHT-?zi_ZIV!PG{PF$b7V{L( zNah{gdpB&^Bv`esXVdfAn12GtDrPagf7I{4JZP!Rt@aE20WV798$P_M6EKs|c+bGG zzGhv+_IdI_L4Jh}#oNAXeh^+!{ounTXTG=lE0|a9v8#B#+HXbHhwN9mVf%02V9md> z?clp-#R^_UYqURFgfncNvwr)U=hq*m1lgQRoB3gH>eoa*@9F&d$>k1g?bp48c~Y*t ztx!2`H}}!TOsTC+n^uW;>_6(qb?E={f@!f;s~^1%QD63HRmIn=A8nSua&8CSRP@!*%Y!T_y$w1_n=8 KKbLh*2~7ZftovC2 literal 0 HcmV?d00001 diff --git a/packages/integration_test/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/packages/integration_test/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..4cde12118dda48d71e01fcb589a74d069c5d7cb5 GIT binary patch literal 1025 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 Ap8x;= literal 0 HcmV?d00001 diff --git a/packages/integration_test/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/packages/integration_test/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..c8f9ed8f5cee1c98386d13b17e89f719e83555b2 GIT binary patch literal 1895 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 jx+3^aWbGD-xb9H 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

i)x2+E zxb%Qx!oO#)noag>?LC&0@xJcT6^1m1SdYISs@Ve$*vv?jJ7_TfSBW%l?XCJ1i#duF z8pGsg)Rc+by~Vg?^3ArJ-zJp)bCeC8!OUH!uMI<9JgXt^-@M|*8@BYwyux_ zNlH3ohZ=V^T6wuUFmB;KX>&+`Sj! zm%W`7+M8&#(I7 zL7buVQ1ptcDS12kdjg9kAGq&IG-Ewc>MN36Arip+;*WbpoO)^0*%kYz_jK2t6-`z= z{HKF;Gs~?t+0T9@I`;lzT)^FQ>#g71FymM6)E+lkimZ-wcqYOYb%mGxg4UI+Am%KF zxAlJo4AzSqykG7Z{CslZyRRav_sw?{b+FfIjH}_ea5rFa9m9)9lXh(hC|CddtA+LR zliMdO(#4Lhs`GxP!nSMKMW$W5i&EI4ES9O5zG83qwl;YA!I)BGN&9_WNy5)2TTX0T zSLeXAcSHPwKzoKQ|GzF~e|A3OLW}fCi^oP?p?AEV{jkN#lIStuw7W^Y+Lg7xzMxPk{c`L zPd3aEI(lxl>oZq#uLYJ1_4l)Apc2lMZl4!jF&SIX}_dB$LVy`-di|FRo5 z?Ug^@nJM&QXG++;gAVt7)2_Zx=@)a*e`P$i`0bUzHS!F*9=vq7=XMo+#x3#e{T%OS z{L3c(Tzpz*f&QMxGZ*(OZBClUTJp7due4TW!=3o$eNjQo8R854R!cHH6F#T>`OC_b zIdR_4X4)$jKbe{mS0H=1X7$bSUuP`=hqhX{-r< z&rFVO-eni{)tNz-ebQ0wi+}g+<=j>I)6GcD#)a9%>YAyj=~fNXD}gKInO^8OBxk;I zce>WUb9J0@a?N7a(%Q}M9o%2OX=nJA{M4|qt2N5W=sSP3#H)6Ot=nG-IP7O$;LTgg z6;NHjox4`2;osyx4C(yJldc$keHt^{`QpmA(*Kt+{0gkz$S1Nm+}^2Z!O67pUWO{O zhBCodOZI(LcA2ejw!55jf%`(|-xpTCHu20Von2F$F!|QLgI}3mEWY`hp|s_-`v!iK zn`gTIPEl+Vh_B?_s(kCK@`2g<-+D#fXGP{Q+s4-!F@9MTZO>FS&r0$At)p$a{~p-% zybG}3Bx`$BCTn-7PgvtWqiX&I-^^E@UcOQK&-Vi_y)zi>53>10`tZPyi zM1J+uF5xZSxhKcv?T3xQ;bxNzKPJ9x{r4-WO!R&qXHDeBhFNhp^8VV+T2dBpyEJ)e z%8oO?`oA8W`AL4_1v#g?s){?azuwP0qw62|G=JX0ji00cexJKG4c?!0~d z;%@)9*E6n|trpF)=+-u@{JE;up4psVergEU_KgNJj`mhfw{6Jfvd(t5JyveFHpgP+ zv!;BDvepA1r$Z02T%q;2+UteW|l+hKwp_rc{wO_3{Q z54lg+THV2_w8ZMlb1~}X4G98W1t+8Ey@6L6lz&N?1 zb4)%3;9InDgIP53^_Ar=ajus zaqE}f+x~p(LANC5ETz>7?~9fc?OfRGA(t`f`u;=v8uwnmIB`Qo&$lH1wWbTjN(h45_6H)5y$e2)n^F!8~` z7W0{`2@A{0w5zRtug=>0VXL+{N7>HD#YxLQ3Vq|+6z9a;a9HzVuY7v^LA!%Lqiq5d z(!F!i-6zHV*7FfcH9y85}Sb4q9e0QKHA1^@s6 literal 0 HcmV?d00001 diff --git a/packages/integration_test/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/packages/integration_test/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..c4df70d39da7941ef3f6dcb7f06a192d8dcb308d GIT binary patch literal 1888 zcmeAS@N?(olHy`uVBq!ia0y~yVDJH94mJh`hU3!%wHX-L)jeGtLn>~)ol~77;wp3e zd*9(B^+)V|Sb7bYEevxsNN95Ly>R5pG><4!#}uyGs~mG-mhw@#=)jY|P(&$f z(L{!c<|0R&xLsVAeA3`bV(L)P-SU0k-1Wx0t*`Gaz6}C*cPCHEH}hRrY(4+)xqLb6 z?~|7>axw5eng)r>M#OO6het&Tdk2 zjXO>(+e6iPSaKw;noN1MNY&D7-9 z9Z#(y_{7gW;WTWkedtzxQflox4oCOxJ(tZ>=XklBr<7cJy-_c6<>4pH4?fl?x10LB zUanWU;8yb0cTa*E9!y=F=<`RhcVRJK?2;*CnExqm)o;lS z(_0muYo!}TY}Q!gDH0YN&0*T!lU-HKk;?A$3ME+W%-nlh&G( zYqi#7w)d=_SNG47E1R)ZRCQX3>^`9zM;c0Z98ElV&WL;Ul!LD}@Jx$1`kp6Zy7Z&z zq35)=UW+`bs<1OLr6kk*if+)p16o@dr#(JUbTYD!d9&7m+nlEj6L!APIo|Me)n*yS zw9JP08|0_0J)rZpjql(l-Wg8~z02~J>E3O6s+2Iz-%GY_YG}gGXKU6lo&LJAdF_Eu zlGC0ZND6zGzEfb@(gQJjem=KL*tyO1v4+9!Ij%-iv>R?dT(jrpq_Uig0uOhuYvcIG zyL@?eNUUJf=`V8Ci}{!y^X{DEn*NdfQ9tARe^P<>OwDBY65Vze?sc$_FEwb{dHfKU zgZ8fFDQsewcg8i%bU$=TI&Jk_)k9U!Dt5c6&wE?JMFt*Z-FYo0As$ecG9_ zqm#{3o~{hfG@mXTA-MG7*Qmd4_bNWWPjKg!s^@yVi_Ke2@5Q9_>W-pf(Y41GEPbuR zrXBnJTB=}}o8$cRuWr7SDC<)cH8I}s%J&F!S$;|s5X-lTtY`+C7ri2H`K`R|V* z-U6n%?^;q{KC-@>0}Nr`<` zdy7|@ZO+jI+fB+1?c3Nt7=&(Q%qX+gel6W0{>Me~V~<7m;YVJqXEh@tZ!db6|Iuc` z=1HRM+qU!H3TaPF{i@3GlKqauxmV(|o^841>^Mc9!-`FN^?@%BHZHz@M$s)n)meJ~ z@%~lcG^FbLG`KU>6K=Bg{1-~Tc2VHnttZD9mze0>%;TBClpC$zRes!{?(_W@T&sSY z7~Y&Y*Qi=%8KZTL@39%Nj3T+b2}>N?r{=sp+94)+c>f>ndtI&-nJ44kDhe#Uw}(Zo zY<~Q%l%9K;JW(gF$#Hcr$T&RzL#TdJ`7JLG;pq>LF8zJgD)slmn^ku-XR&Rui+KKU zbp*%CEY3Y&eI;xba|ZnkI=d!JZ8gy^*`Pg~05HAUF3_{)t-pO$Th`yYuVR1~wb^{#6$ zS;cm56aRyiaZ=?|=e=or_JdzKWVxWs`)MB&K5JIYpTnE~vPLwh*7)kJy2QepH*F;i zj@KU*yZTHfSN+^$J~OUsYn%I>K3rMn$N9S6&s)OQGpyn6l}L4K_P1~BB`!HE3|-%p zUo|-~!OT+kNWfPS=GuGf-tOyv(_)X+zuy~uCi>%+*^eR~>9s#z_T1;xqn+hj zUhA1VcV9|noLx0zs^_~oM;k4)S9EqoD9uY+#UM1fU$p4qO3gzd%9D%Ve`s+v-pcQu z=NK%p!6@2XU+I_7y4oY`tC(8dSR%TEQ&&Fri(YZLpL=1)!;Fm+R$ZBFB&)f1-?F17 zae;Qnx6Mf45!-yvfW@2rR>rEmR#Q(~^7;GtYKd*rsW_9P7jF15m-VV&?zY+as%vI0 zx>fQh`l0;ZMXIL9_quOo&+2*<(N|_a?c O7(8A5T-G@yGywok=Zg*i literal 0 HcmV?d00001 diff --git a/packages/integration_test/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/packages/integration_test/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..6a84f41e14e27f4b11f16f9ee39279ac98f8d5ac GIT binary patch literal 3294 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 literal 0 HcmV?d00001 diff --git a/packages/integration_test/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/packages/integration_test/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json new file mode 100644 index 0000000000..0bedcf2fd4 --- /dev/null +++ b/packages/integration_test/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "LaunchImage.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/packages/integration_test/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png b/packages/integration_test/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png new file mode 100644 index 0000000000000000000000000000000000000000..9da19eacad3b03bb08bbddbbf4ac48dd78b3d838 GIT binary patch literal 68 zcmeAS@N?(olHy`uVBq!ia0y~yU|@r242}Q* literal 0 HcmV?d00001 diff --git a/packages/integration_test/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/packages/integration_test/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..9da19eacad3b03bb08bbddbbf4ac48dd78b3d838 GIT binary patch literal 68 zcmeAS@N?(olHy`uVBq!ia0y~yU|@r242}Q* literal 0 HcmV?d00001 diff --git a/packages/integration_test/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/packages/integration_test/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..9da19eacad3b03bb08bbddbbf4ac48dd78b3d838 GIT binary patch literal 68 zcmeAS@N?(olHy`uVBq!ia0y~yU|@r242}Q* literal 0 HcmV?d00001 diff --git a/packages/integration_test/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/packages/integration_test/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md new file mode 100644 index 0000000000..89c2725b70 --- /dev/null +++ b/packages/integration_test/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md @@ -0,0 +1,5 @@ +# Launch Screen Assets + +You can customize the launch screen with your own desired assets by replacing the image files in this directory. + +You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. \ No newline at end of file diff --git a/packages/integration_test/example/ios/Runner/Base.lproj/LaunchScreen.storyboard b/packages/integration_test/example/ios/Runner/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 0000000000..f2e259c7c9 --- /dev/null +++ b/packages/integration_test/example/ios/Runner/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/integration_test/example/ios/Runner/Base.lproj/Main.storyboard b/packages/integration_test/example/ios/Runner/Base.lproj/Main.storyboard new file mode 100644 index 0000000000..f3c28516fb --- /dev/null +++ b/packages/integration_test/example/ios/Runner/Base.lproj/Main.storyboard @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/integration_test/example/ios/Runner/Info.plist b/packages/integration_test/example/ios/Runner/Info.plist new file mode 100644 index 0000000000..d0e099be56 --- /dev/null +++ b/packages/integration_test/example/ios/Runner/Info.plist @@ -0,0 +1,45 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + integration_test_example + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleSignature + ???? + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + + + diff --git a/packages/integration_test/example/ios/Runner/main.m b/packages/integration_test/example/ios/Runner/main.m new file mode 100644 index 0000000000..736a65aa5e --- /dev/null +++ b/packages/integration_test/example/ios/Runner/main.m @@ -0,0 +1,13 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import +#import +#import "AppDelegate.h" + +int main(int argc, char* argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/packages/integration_test/example/ios/RunnerTests/Info.plist b/packages/integration_test/example/ios/RunnerTests/Info.plist new file mode 100644 index 0000000000..64d65ca495 --- /dev/null +++ b/packages/integration_test/example/ios/RunnerTests/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + + diff --git a/packages/integration_test/example/ios/RunnerTests/RunnerTests.m b/packages/integration_test/example/ios/RunnerTests/RunnerTests.m new file mode 100644 index 0000000000..5c5aee9002 --- /dev/null +++ b/packages/integration_test/example/ios/RunnerTests/RunnerTests.m @@ -0,0 +1,8 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import +#import + +INTEGRATION_TEST_IOS_RUNNER(RunnerTests) diff --git a/packages/integration_test/example/lib/main.dart b/packages/integration_test/example/lib/main.dart new file mode 100644 index 0000000000..4bb93baf5c --- /dev/null +++ b/packages/integration_test/example/lib/main.dart @@ -0,0 +1,9 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'my_app.dart' if (dart.library.html) 'my_web_app.dart'; + +// ignore_for_file: public_member_api_docs + +void main() => startApp(); diff --git a/packages/integration_test/example/lib/my_app.dart b/packages/integration_test/example/lib/my_app.dart new file mode 100644 index 0000000000..6e31eca3b6 --- /dev/null +++ b/packages/integration_test/example/lib/my_app.dart @@ -0,0 +1,31 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:io' show Platform; +import 'package:flutter/material.dart'; + +// ignore_for_file: public_member_api_docs + +void startApp() => runApp(MyApp()); + +class MyApp extends StatefulWidget { + @override + _MyAppState createState() => _MyAppState(); +} + +class _MyAppState extends State { + @override + Widget build(BuildContext context) { + return MaterialApp( + home: Scaffold( + appBar: AppBar( + title: const Text('Plugin example app'), + ), + body: Center( + child: Text('Platform: ${Platform.operatingSystem}\n'), + ), + ), + ); + } +} diff --git a/packages/integration_test/example/lib/my_web_app.dart b/packages/integration_test/example/lib/my_web_app.dart new file mode 100644 index 0000000000..d8f17fe1cf --- /dev/null +++ b/packages/integration_test/example/lib/my_web_app.dart @@ -0,0 +1,32 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:html' as html; +import 'package:flutter/material.dart'; + +// ignore_for_file: public_member_api_docs + +void startApp() => runApp(MyWebApp()); + +class MyWebApp extends StatefulWidget { + @override + _MyWebAppState createState() => _MyWebAppState(); +} + +class _MyWebAppState extends State { + @override + Widget build(BuildContext context) { + return MaterialApp( + home: Scaffold( + appBar: AppBar( + title: const Text('Plugin example app'), + ), + body: Center( + key: const Key('mainapp'), + child: Text('Platform: ${html.window.navigator.platform}\n'), + ), + ), + ); + } +} diff --git a/packages/integration_test/example/macos/Flutter/ephemeral/Flutter-Generated.xcconfig b/packages/integration_test/example/macos/Flutter/ephemeral/Flutter-Generated.xcconfig new file mode 100644 index 0000000000..2665978cd8 --- /dev/null +++ b/packages/integration_test/example/macos/Flutter/ephemeral/Flutter-Generated.xcconfig @@ -0,0 +1,11 @@ +// This is a generated file; do not edit or check into version control. +FLUTTER_ROOT=/Users/dnfield/src/flutter/flutter +FLUTTER_APPLICATION_PATH=/Users/dnfield/src/flutter/flutter/packages/integration_test/example +FLUTTER_BUILD_DIR=build +FLUTTER_FRAMEWORK_DIR=/Users/dnfield/src/flutter/flutter/bin/cache/artifacts/engine/darwin-x64 +FLUTTER_BUILD_NAME=1.0.0 +FLUTTER_BUILD_NUMBER=1 +DART_OBFUSCATION=false +TRACK_WIDGET_CREATION=false +TREE_SHAKE_ICONS=false +PACKAGE_CONFIG=.packages diff --git a/packages/integration_test/example/macos/Flutter/ephemeral/flutter_export_environment.sh b/packages/integration_test/example/macos/Flutter/ephemeral/flutter_export_environment.sh new file mode 100755 index 0000000000..04c4e6facd --- /dev/null +++ b/packages/integration_test/example/macos/Flutter/ephemeral/flutter_export_environment.sh @@ -0,0 +1,12 @@ +#!/bin/sh +# This is a generated file; do not edit or check into version control. +export "FLUTTER_ROOT=/Users/dnfield/src/flutter/flutter" +export "FLUTTER_APPLICATION_PATH=/Users/dnfield/src/flutter/flutter/packages/integration_test/example" +export "FLUTTER_BUILD_DIR=build" +export "FLUTTER_FRAMEWORK_DIR=/Users/dnfield/src/flutter/flutter/bin/cache/artifacts/engine/darwin-x64" +export "FLUTTER_BUILD_NAME=1.0.0" +export "FLUTTER_BUILD_NUMBER=1" +export "DART_OBFUSCATION=false" +export "TRACK_WIDGET_CREATION=false" +export "TREE_SHAKE_ICONS=false" +export "PACKAGE_CONFIG=.packages" diff --git a/packages/integration_test/example/macos/Podfile b/packages/integration_test/example/macos/Podfile new file mode 100644 index 0000000000..d60ec71028 --- /dev/null +++ b/packages/integration_test/example/macos/Podfile @@ -0,0 +1,82 @@ +platform :osx, '10.11' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def parse_KV_file(file, separator='=') + file_abs_path = File.expand_path(file) + if !File.exists? file_abs_path + return []; + end + pods_ary = [] + skip_line_start_symbols = ["#", "/"] + File.foreach(file_abs_path) { |line| + next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ } + plugin = line.split(pattern=separator) + if plugin.length == 2 + podname = plugin[0].strip() + path = plugin[1].strip() + podpath = File.expand_path("#{path}", file_abs_path) + pods_ary.push({:name => podname, :path => podpath}); + else + puts "Invalid plugin specification: #{line}" + end + } + return pods_ary +end + +def pubspec_supports_macos(file) + file_abs_path = File.expand_path(file) + if !File.exists? file_abs_path + return false; + end + File.foreach(file_abs_path) { |line| + return true if line =~ /^\s*macos:/ + } + return false +end + +target 'Runner' do + use_frameworks! + use_modular_headers! + + # Prepare symlinks folder. We use symlinks to avoid having Podfile.lock + # referring to absolute paths on developers' machines. + ephemeral_dir = File.join('Flutter', 'ephemeral') + symlink_dir = File.join(ephemeral_dir, '.symlinks') + symlink_plugins_dir = File.join(symlink_dir, 'plugins') + system("rm -rf #{symlink_dir}") + system("mkdir -p #{symlink_plugins_dir}") + + # Flutter Pods + generated_xcconfig = parse_KV_file(File.join(ephemeral_dir, 'Flutter-Generated.xcconfig')) + if generated_xcconfig.empty? + puts "Flutter-Generated.xcconfig must exist. If you're running pod install manually, make sure flutter packages get is executed first." + end + generated_xcconfig.map { |p| + if p[:name] == 'FLUTTER_FRAMEWORK_DIR' + symlink = File.join(symlink_dir, 'flutter') + File.symlink(File.dirname(p[:path]), symlink) + pod 'FlutterMacOS', :path => File.join(symlink, File.basename(p[:path])) + end + } + + # Plugin Pods + plugin_pods = parse_KV_file('../.flutter-plugins') + plugin_pods.map { |p| + symlink = File.join(symlink_plugins_dir, p[:name]) + File.symlink(p[:path], symlink) + if pubspec_supports_macos(File.join(symlink, 'pubspec.yaml')) + pod p[:name], :path => File.join(symlink, 'macos') + end + } +end + +# Prevent Cocoapods from embedding a second Flutter framework and causing an error with the new Xcode build system. +install! 'cocoapods', :disable_input_output_paths => true diff --git a/packages/integration_test/example/macos/Runner.xcodeproj/project.pbxproj b/packages/integration_test/example/macos/Runner.xcodeproj/project.pbxproj new file mode 100644 index 0000000000..718462e3b4 --- /dev/null +++ b/packages/integration_test/example/macos/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,656 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 51; + objects = { + +/* Begin PBXAggregateTarget section */ + 33CC111A2044C6BA0003C045 /* Flutter Assemble */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */; + buildPhases = ( + 33CC111E2044C6BF0003C045 /* ShellScript */, + ); + dependencies = ( + ); + name = "Flutter Assemble"; + productName = FLX; + }; +/* End PBXAggregateTarget section */ + +/* Begin PBXBuildFile section */ + 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; }; + 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; }; + 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; }; + 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; + 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; + 33D1A10422148B71006C7A3E /* FlutterMacOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 33D1A10322148B71006C7A3E /* FlutterMacOS.framework */; }; + 33D1A10522148B93006C7A3E /* FlutterMacOS.framework in Bundle Framework */ = {isa = PBXBuildFile; fileRef = 33D1A10322148B71006C7A3E /* FlutterMacOS.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + B7C0D6D07EB453D3AC9C81F2 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A2D6D92F7F9105EA5B2C12C6 /* Pods_Runner.framework */; }; + D73912F022F37F9E000D13A0 /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D73912EF22F37F9E000D13A0 /* App.framework */; }; + D73912F222F3801D000D13A0 /* App.framework in Bundle Framework */ = {isa = PBXBuildFile; fileRef = D73912EF22F37F9E000D13A0 /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 33CC10E52044A3C60003C045 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 33CC111A2044C6BA0003C045; + remoteInfo = FLX; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 33CC110E2044A8840003C045 /* Bundle Framework */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + D73912F222F3801D000D13A0 /* App.framework in Bundle Framework */, + 33D1A10522148B93006C7A3E /* FlutterMacOS.framework in Bundle Framework */, + ); + name = "Bundle Framework"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 2A162B3576CC7562C04C8319 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; + 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; }; + 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; }; + 33CC10ED2044A3C60003C045 /* integration_test_example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = integration_test_example.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = ""; }; + 33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; + 33CC10F72044A3C60003C045 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = Runner/Info.plist; sourceTree = ""; }; + 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainFlutterWindow.swift; sourceTree = ""; }; + 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Debug.xcconfig"; sourceTree = ""; }; + 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Release.xcconfig"; sourceTree = ""; }; + 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = "Flutter-Generated.xcconfig"; path = "ephemeral/Flutter-Generated.xcconfig"; sourceTree = ""; }; + 33D1A10322148B71006C7A3E /* FlutterMacOS.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = FlutterMacOS.framework; path = Flutter/ephemeral/FlutterMacOS.framework; sourceTree = SOURCE_ROOT; }; + 33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = ""; }; + 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; }; + 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; }; + 710A00C7116252C03437F6D9 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; + 97614001DA7FEA4B30ABAB1F /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + A2D6D92F7F9105EA5B2C12C6 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + D73912EF22F37F9E000D13A0 /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/ephemeral/App.framework; sourceTree = SOURCE_ROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 33CC10EA2044A3C60003C045 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + D73912F022F37F9E000D13A0 /* App.framework in Frameworks */, + 33D1A10422148B71006C7A3E /* FlutterMacOS.framework in Frameworks */, + B7C0D6D07EB453D3AC9C81F2 /* Pods_Runner.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 2B3E7A30398192ADA2835AB3 /* Pods */ = { + isa = PBXGroup; + children = ( + 710A00C7116252C03437F6D9 /* Pods-Runner.debug.xcconfig */, + 2A162B3576CC7562C04C8319 /* Pods-Runner.release.xcconfig */, + 97614001DA7FEA4B30ABAB1F /* Pods-Runner.profile.xcconfig */, + ); + path = Pods; + sourceTree = ""; + }; + 33BA886A226E78AF003329D5 /* Configs */ = { + isa = PBXGroup; + children = ( + 33E5194F232828860026EE4D /* AppInfo.xcconfig */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 333000ED22D3DE5D00554162 /* Warnings.xcconfig */, + ); + path = Configs; + sourceTree = ""; + }; + 33CC10E42044A3C60003C045 = { + isa = PBXGroup; + children = ( + 33FAB671232836740065AC1E /* Runner */, + 33CEB47122A05771004F2AC0 /* Flutter */, + 33CC10EE2044A3C60003C045 /* Products */, + D73912EC22F37F3D000D13A0 /* Frameworks */, + 2B3E7A30398192ADA2835AB3 /* Pods */, + ); + sourceTree = ""; + }; + 33CC10EE2044A3C60003C045 /* Products */ = { + isa = PBXGroup; + children = ( + 33CC10ED2044A3C60003C045 /* integration_test_example.app */, + ); + name = Products; + sourceTree = ""; + }; + 33CC11242044D66E0003C045 /* Resources */ = { + isa = PBXGroup; + children = ( + 33CC10F22044A3C60003C045 /* Assets.xcassets */, + 33CC10F42044A3C60003C045 /* MainMenu.xib */, + 33CC10F72044A3C60003C045 /* Info.plist */, + ); + name = Resources; + path = ..; + sourceTree = ""; + }; + 33CEB47122A05771004F2AC0 /* Flutter */ = { + isa = PBXGroup; + children = ( + 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */, + 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */, + 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */, + 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */, + D73912EF22F37F9E000D13A0 /* App.framework */, + 33D1A10322148B71006C7A3E /* FlutterMacOS.framework */, + ); + path = Flutter; + sourceTree = ""; + }; + 33FAB671232836740065AC1E /* Runner */ = { + isa = PBXGroup; + children = ( + 33CC10F02044A3C60003C045 /* AppDelegate.swift */, + 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */, + 33E51913231747F40026EE4D /* DebugProfile.entitlements */, + 33E51914231749380026EE4D /* Release.entitlements */, + 33CC11242044D66E0003C045 /* Resources */, + 33BA886A226E78AF003329D5 /* Configs */, + ); + path = Runner; + sourceTree = ""; + }; + D73912EC22F37F3D000D13A0 /* Frameworks */ = { + isa = PBXGroup; + children = ( + A2D6D92F7F9105EA5B2C12C6 /* Pods_Runner.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 33CC10EC2044A3C60003C045 /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + 10BA06117B193C37CD021555 /* [CP] Check Pods Manifest.lock */, + 33CC10E92044A3C60003C045 /* Sources */, + 33CC10EA2044A3C60003C045 /* Frameworks */, + 33CC10EB2044A3C60003C045 /* Resources */, + 33CC110E2044A8840003C045 /* Bundle Framework */, + 3399D490228B24CF009A79C7 /* ShellScript */, + FC41FCCE1DD077B5F6ABF89F /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 33CC11202044C79F0003C045 /* PBXTargetDependency */, + ); + name = Runner; + productName = Runner; + productReference = 33CC10ED2044A3C60003C045 /* integration_test_example.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 33CC10E52044A3C60003C045 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0920; + LastUpgradeCheck = 0930; + ORGANIZATIONNAME = "Google LLC"; + TargetAttributes = { + 33CC10EC2044A3C60003C045 = { + CreatedOnToolsVersion = 9.2; + LastSwiftMigration = 1100; + ProvisioningStyle = Automatic; + SystemCapabilities = { + com.apple.Sandbox = { + enabled = 1; + }; + }; + }; + 33CC111A2044C6BA0003C045 = { + CreatedOnToolsVersion = 9.2; + ProvisioningStyle = Manual; + }; + }; + }; + buildConfigurationList = 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 8.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 33CC10E42044A3C60003C045; + productRefGroup = 33CC10EE2044A3C60003C045 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 33CC10EC2044A3C60003C045 /* Runner */, + 33CC111A2044C6BA0003C045 /* Flutter Assemble */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 33CC10EB2044A3C60003C045 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */, + 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 10BA06117B193C37CD021555 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + 3399D490228B24CF009A79C7 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "echo \"$PRODUCT_NAME.app\" > \"$PROJECT_DIR\"/Flutter/ephemeral/.app_filename\n"; + }; + 33CC111E2044C6BF0003C045 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + Flutter/ephemeral/FlutterInputs.xcfilelist, + ); + inputPaths = ( + Flutter/ephemeral/tripwire, + ); + outputFileListPaths = ( + Flutter/ephemeral/FlutterOutputs.xcfilelist, + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh\ntouch Flutter/ephemeral/tripwire\n"; + }; + FC41FCCE1DD077B5F6ABF89F /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 33CC10E92044A3C60003C045 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */, + 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */, + 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 33CC11202044C79F0003C045 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 33CC111A2044C6BA0003C045 /* Flutter Assemble */; + targetProxy = 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 33CC10F42044A3C60003C045 /* MainMenu.xib */ = { + isa = PBXVariantGroup; + children = ( + 33CC10F52044A3C60003C045 /* Base */, + ); + name = MainMenu.xib; + path = Runner; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 338D0CE9231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = Profile; + }; + 338D0CEA231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter/ephemeral", + ); + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = 10.11; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + }; + name = Profile; + }; + 338D0CEB231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Manual; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Profile; + }; + 33CC10F92044A3C60003C045 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 33CC10FA2044A3C60003C045 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = Release; + }; + 33CC10FC2044A3C60003C045 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter/ephemeral", + ); + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = 10.11; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + 33CC10FD2044A3C60003C045 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter/ephemeral", + ); + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = 10.11; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; + 33CC111C2044C6BA0003C045 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Manual; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 33CC111D2044C6BA0003C045 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC10F92044A3C60003C045 /* Debug */, + 33CC10FA2044A3C60003C045 /* Release */, + 338D0CE9231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC10FC2044A3C60003C045 /* Debug */, + 33CC10FD2044A3C60003C045 /* Release */, + 338D0CEA231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC111C2044C6BA0003C045 /* Debug */, + 33CC111D2044C6BA0003C045 /* Release */, + 338D0CEB231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 33CC10E52044A3C60003C045 /* Project object */; +} diff --git a/packages/integration_test/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/packages/integration_test/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 0000000000..464e05225e --- /dev/null +++ b/packages/integration_test/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/integration_test/example/macos/Runner.xcworkspace/contents.xcworkspacedata b/packages/integration_test/example/macos/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000000..1d526a16ed --- /dev/null +++ b/packages/integration_test/example/macos/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/packages/integration_test/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/packages/integration_test/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000000..18d981003d --- /dev/null +++ b/packages/integration_test/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/packages/integration_test/example/macos/Runner/AppDelegate.swift b/packages/integration_test/example/macos/Runner/AppDelegate.swift new file mode 100644 index 0000000000..d080d41951 --- /dev/null +++ b/packages/integration_test/example/macos/Runner/AppDelegate.swift @@ -0,0 +1,13 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import Cocoa +import FlutterMacOS + +@NSApplicationMain +class AppDelegate: FlutterAppDelegate { + override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { + return true + } +} diff --git a/packages/integration_test/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/packages/integration_test/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000000..a2ec33f19f --- /dev/null +++ b/packages/integration_test/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,68 @@ +{ + "images" : [ + { + "size" : "16x16", + "idiom" : "mac", + "filename" : "app_icon_16.png", + "scale" : "1x" + }, + { + "size" : "16x16", + "idiom" : "mac", + "filename" : "app_icon_32.png", + "scale" : "2x" + }, + { + "size" : "32x32", + "idiom" : "mac", + "filename" : "app_icon_32.png", + "scale" : "1x" + }, + { + "size" : "32x32", + "idiom" : "mac", + "filename" : "app_icon_64.png", + "scale" : "2x" + }, + { + "size" : "128x128", + "idiom" : "mac", + "filename" : "app_icon_128.png", + "scale" : "1x" + }, + { + "size" : "128x128", + "idiom" : "mac", + "filename" : "app_icon_256.png", + "scale" : "2x" + }, + { + "size" : "256x256", + "idiom" : "mac", + "filename" : "app_icon_256.png", + "scale" : "1x" + }, + { + "size" : "256x256", + "idiom" : "mac", + "filename" : "app_icon_512.png", + "scale" : "2x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "app_icon_512.png", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "app_icon_1024.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/packages/integration_test/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png b/packages/integration_test/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png new file mode 100644 index 0000000000000000000000000000000000000000..3c4935a7ca84f0976aca34b7f2895d65fb94d1ea GIT binary patch literal 46993 zcmeAS@N?(olHy`uVBq!ia0y~yU||4Z4mJh`hI(1;W)Lsk(btiIVPik{pF~y$1_p&> zk04(LhAK4%hK3dfhF=T}3=Ji(0|NtRfk$L90|U1(2s1Lwnj^u$z`$PO>Fdh=n3I*mh+C+-w~v9Lfx*+oF{I+w zo4=7W=3Jfo{P(|WT^%85UQR+mSq>fv(&3@+*R5N(?(&s)x5S@Uo^zew{dtbr7D2Y@ zjHjR9m{B>e#jS^t`55c6Rp(!>UbT1cce~yCzw+$aj5|&?^yZovN=2^v)G*UAc-a)e zkL!vBKc>00DFsW;%s*0ff9t;ab>BAcUab(B?aKH5yL`Tj2Ll2u_|fwo6bK@BkA)wb z{oh>u`J6eQ_b&R$oxttL@vx91k>B;U%lT=ygZlsfu9x_-*Y}L$&F@SM3=Ca5z4ggG zbBeiDbSJ0OuIFZ`TA=kZ*|YO~YeF6<2pG;>O!+hYNlfj+;$Qxg>NH-O+|Ooi=m}N* z8*=HoO6{X+!x_?`NMR_RaBTlpRaMX0g~ji@Csl`BDuO6X{nEAecDA;<)_gV9JO&M| zJbz{eh8LGo{!H(zXIQxU)C<<=?cqE

@If>gQBaQUX7oU}Rt@QSANiwRDlnO2PjO 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 literal 0 HcmV?d00001 diff --git a/packages/integration_test/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png b/packages/integration_test/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png new file mode 100644 index 0000000000000000000000000000000000000000..ed4cc16421680a50164ba74381b4b35ceaa0ccfc GIT binary patch literal 3276 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 literal 0 HcmV?d00001 diff --git a/packages/integration_test/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png b/packages/integration_test/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png new file mode 100644 index 0000000000000000000000000000000000000000..483be61389733f2e5331c08db8ca245268610ccb GIT binary patch literal 1429 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4rT@h1`S>QUNSs54@ z6p}rHd>I(3)EF2VS{N99F)%PRykKA`HDF+PmB7GYHG_dcykO3*KpO@IrilSQA+8Jz z3<)QHB%J&a4@Pk(e#C-N^obwQ$Dt_knGknI zo%j)T>_^0LgcgVbWD;U5#CDL!krYQBhXx=-JwzqMF1YujU@i$g{wwl0$b}GPkN{6S z`9po{SNnb6!;gVO71eNv`Ed2|Cx7T}|7N`No6*j1c6+~vfwcULMA8B=GxGQkhO&1? zU}c6ozZvfOZn62D^O{Enlh0Ou`X7E2q}^cWH;@!qR%gvC;o`0AQFGWpXfA8iT$ac= zQ0+Uu8Seh6z3QcC!Dfz#+3Zns*`lBdm?P#eMa(wb`ORSGH=(=@LirovvJexPBjzwi z%wY_lt-s@&`nuPmr8^*c;j&B-vl%01Geyk)|Np;2#5@xQ28LTDL4KeF&ft9i+t(ip z_!t-%7_6@S|NnoR9EizaedGWC|664+*eDXH90n*?8mx(tfx+Y^$P6iwrkOKlSMW11 znBM&Vf2)-6%K!iWKk))7vc9nm!o3g5CkzY>I#Qw_*?UkfL*M`Z|9`}Qlrq?X9JC4I zAc#duOMw?drla{v1`kZ&x447eE>7#Neh-Cb_IV^(WoU|`@Z@Q5sCVBi)8VMc~o zb0ioT7}!fZeO=ifbFy+6aSK)V_AxLpvU$2VhDcmaPGDekQ%e&IGb`is)5|lM-#)!R z-XXvv!X?B<=E(F3QzlKDICXM(KuAy+T|ZYeGK`h~Zl##uR8IM}$D+gm$Z zI$GiWxqAmMp1gVV>e;)8FQ2}BeEPxj_6i0X7Aht>HcCcXR%+7}_3RW4H7!+5b#0Z6 zwXM~sE9&oGuwliHC0o|)S+r@@u4U5}uG_b8->LBt=(e!k-Kt!c1=xaH(nF9H|_1NuhM3DxAvrJM&5S^di$$)Hp5cCn7SJ(<$oC% z7*tDKBT7;dOH!?pi&7IyQW=a43@vpHEOiY`Lkvx=Obx6I4RsC7tqcqn=oIIoXvob^ Z$xN%nt>I$f>5HKF^>p=fS?83{1OQU9x^Vyi literal 0 HcmV?d00001 diff --git a/packages/integration_test/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png b/packages/integration_test/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png new file mode 100644 index 0000000000000000000000000000000000000000..bcbf36df2f2aaaa0a63c7dabc94e600184229d0d GIT binary patch literal 5933 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 I&MBb@0FMIvLjV8( literal 0 HcmV?d00001 diff --git a/packages/integration_test/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png b/packages/integration_test/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png new file mode 100644 index 0000000000000000000000000000000000000000..9c0a652864769b250ed58097f2f6270b393f751f GIT binary patch literal 1243 zcmeAS@N?(olHy`uVBq!ia0y~yU{C;I4mJh`hT^KKFANL}Ea{HEjtmSN`?>!lvVtU& zJ%W507^>757#dm_7=AG@Ff_biU???UV0e|lz+g3lfkC`r&aOZk1_lPUByV>YhW{YA zVDIwD3=9mM1s;*b3=G`DAk4@xYmNj10|R@Br>`sfV@_5MBW|JU-aZBf=2M<7jv*0; z*G`YkkO>tzUY}kj{h9HYNQ;>Kk#C+Ylio~jQh0K7-_I;o-{#p398Cf>pVoG)Sg2on zhV96;W&NS?CM^oB)6_bqEK*gywWTxUx1y=M^cp8dtDn!i z|9?*L`<>QK({poHa;>P9VLG>>C`NI^+*ff^WeS`VnIbIzN9i;C%zL0debo!QKamfL zAFw=F>L>JW!5pE8!rhnEw=^^>{r<4N;iTENYYj?=YKj&pGd}*fA^HbPgzd@?o(Tv2 z{+jXByEE~~9NA#iKKrDhMM?~_*u9m{A028eUjNN(&lNMK$cL*oW=?#*ZMWo}wGDZ; z$3MnI9f;=gXx7$xpyO)Jb#e}Kdh~%{))FrM!}ksExV>0;=xv3Vg~Pd8id8>+dAg&xyz$De>dto9nMVfSW{*?tz9&&A^BqA9gV}xdQ9>= z=bj9@b0vHEsiO}L+SQ0@n4Ia3-_LHx_D(hQ<}>E`4632bTlcH%Io`}0f6`NCooA8E zKgI%cO(QYJP_xFBA2z;_h+tM@70co>|IZyDaqm`gnS#FW!@f4QA9IS8tZr`*s$6Zr z;nS{^mn`d+MiGuYMeKJ|DlM>{oVG zyncYC^}S1VYK(~+CAn6oY?Q1?|EvEm@?Wd%{r|x(YK=z~42sIn@1LJ#e|dh8p<;c@ z%|%N&*09Cx+kEh^_US8Sr#Om2LeoP^L!7?z?J>T+w;}%ioAS?lIek{nN^0f!cgu=j zKX&Q9y~13f4a%#|tT4(_f95}B)~)>6Ot;+*ZB4M-oFY)NYtOd0nu5xickgmJ-g9=I zKDVlfJJ?yw^v#;HM~!DhG938O?{?(gH$EwrX6et}mv{I7RpKmA5ec{&eV|3FyKGHe zV!VrcyxaA@@3;AV<<|b&_%c7&Pcf+IJWuao#=Zo*3&JLx(0 zpN;zEZCv)mi0)vKVR5_Cxq`Q{LXznoLtetArhng@%b6ImuJ2c_f1~?5B6J7S9*#W= zR;8Xf`D*nn?FZVo*!L_tmHHsQ&YbBVyNu$awNG26Ef^RWR7+eVN>UO_QmvAUQWHy3 z8H@}JEp-hnbq!2I3{9;}4Xg|ebq&m|3=9_N6z8I7$jwj5OsmAL;bP(Giwq1544$rj JF6*2UngAMu6(#@x literal 0 HcmV?d00001 diff --git a/packages/integration_test/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png b/packages/integration_test/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png new file mode 100644 index 0000000000000000000000000000000000000000..e71a726136a47ed24125c7efc79d68a4a01961b4 GIT binary patch literal 14800 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 U3r}BUU|?YIboFyt=akR{00MO-p8x;= literal 0 HcmV?d00001 diff --git a/packages/integration_test/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png b/packages/integration_test/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png new file mode 100644 index 0000000000000000000000000000000000000000..8a31fe2dd3f91d79cab6e0390356bb3c1a355f94 GIT binary patch literal 1874 zcmeAS@N?(olHy`uVBq!ia0y~yU~m9o4mJh`hE| zgW!U_%O^81FmM)lL>4nJa0`PlBg3pY5)2Fs>?NMQuI!IFSvicjg{ph|7#P?bJzX3_ zDsJ7K{k}USRN}b(`MEdcCExA75pb}n&LLyUzJQnf8k4ppbZ+?MuBofI_YM0$ej&w| z-8@@DyIBHnd1$yCy`#HgL)F5c%OXn4HkIAIA^+~&nakZfH&>@U`)Bd}+}`qKayvGZ zKf7c7{B!NR;&;XKY{OqL+%~Kdzi{hiR_HfoerC}#`BFZ$|IGYkS``!Q1FZI~-2PJT zCtq_sV~xTgv8zA6o4he8kkR0LbaTO4CX)l}S@@XFtCsu@J}{f9RY7;|e`A{f27#93 z*;Q8V4Obo><=dyr^hRcHcgn-cm52CQ4=_L3)V97d?h;?MV4K;umbfXAEN{*fo#{5% zq9|i$%vhFca@)Q2yi0@DpGA=eXInaWSOq+)f}c6%B!^c|5(m8zk}i7=31Ng*=!$lxdlY+7JUzH&-ZLld1$L6{No0b3h(^~ zf6qKf=A1C~`DBlx9GxIrg;$HuvEBPnw`|_}nWZdmWcFq|E#s>gf-uOy?Jx!0mX#P?w129?ilvJ{`oZa z(BJPIm6`l|rZSic_V8773P|o_yLeso%WkC<-h5q#E6-o@DjjKCKU0!3@{qgG0q2&h z2h1L56e#P}%;nhob>alGniNJG7lU^qeDd2KZ$2-e$o(UNsiG_4!205cM;pTDf4Sy8 zVV~Z@`_@82?ftq9^Vf27R7?MurJLW^67oRtU~Umx4gZHe`8~ct=JAcKTso(@E#22K zRbOgoFWGitPlJD3`d)p9#8oWycjnF0>l3}VyYA_&qi?0F1FpI}R6MAd;Bp}Af%Ai# z7EfhD9a?@`2aCAvyFByIkLMkq#ST?$Z8Rv)2~T2LBFMO3d(XmY-kHLC80XFWxafg} zzLE^XFUBccclG7p*)Y~sRL!i++S*|BFp;zF&nFGzR;3e34SWpjAzS5FCC;A0(P_uZ zFfT@mOJGmgiukbZ4F;9%AH5g*h<87*SfT6|&1%8&vGxm?@cD70&t~ z?mk0SKkT5aqw9rdOJ1mK2){a4IK#Ik#LVm83u76ZZcV+KkAG61<%tQf1}=CMT`L(7 zJ4={h*S4ebd@J9In7Rf?1b>|&>@s8ij>Gex>lv0m4ik-8&F>?6=dcW0cNLF=kucJCm1BDh}ws_v5O3Z-1|)V_@s2<=>Q2KJ7c;e_kj0O-X89Voy=! z28&OBKU}dF*12=r*D{~~{lq}N6|Wcz!ioNo6@htWr{>iz5FN4N5mC!6QG5oUE7-^mXOM>&j7A=eHZHxAsbzj&Pp1#no zHB{nq*0CS0ynFt;?ELYNp&($Y=!3NBa?^gQyhy!!n{T$_e}xZrA115{+jFa$-T88! zYoKd`@{aZAU#C~kTK7ww=lbCc%aV9q1_lPz64!{5l*E!$tK_28#FA77BLhQAT?0#9 z1Je*gQ!7&gD?>wF19K|_g9SRpxhNWP^HVa@DsgMLSa|v(0|Nttr>mdKI;Vst01`nx ALI3~& literal 0 HcmV?d00001 diff --git a/packages/integration_test/example/macos/Runner/Base.lproj/MainMenu.xib b/packages/integration_test/example/macos/Runner/Base.lproj/MainMenu.xib new file mode 100644 index 0000000000..537341abf9 --- /dev/null +++ b/packages/integration_test/example/macos/Runner/Base.lproj/MainMenu.xib @@ -0,0 +1,339 @@ + + + + + + + + + + + + + + + + + + + + + + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/integration_test/example/macos/Runner/Configs/AppInfo.xcconfig b/packages/integration_test/example/macos/Runner/Configs/AppInfo.xcconfig new file mode 100644 index 0000000000..1d9e2f0e04 --- /dev/null +++ b/packages/integration_test/example/macos/Runner/Configs/AppInfo.xcconfig @@ -0,0 +1,14 @@ +// Application-level settings for the Runner target. +// +// This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the +// future. If not, the values below would default to using the project name when this becomes a +// 'flutter create' template. + +// The application's name. By default this is also the title of the Flutter window. +PRODUCT_NAME = integration_test_example + +// The application's bundle identifier +PRODUCT_BUNDLE_IDENTIFIER = com.example.integrationTestExample + +// The copyright displayed in application information +PRODUCT_COPYRIGHT = Copyright © 2019 com.example. All rights reserved. diff --git a/packages/integration_test/example/macos/Runner/Configs/Debug.xcconfig b/packages/integration_test/example/macos/Runner/Configs/Debug.xcconfig new file mode 100644 index 0000000000..36b0fd9464 --- /dev/null +++ b/packages/integration_test/example/macos/Runner/Configs/Debug.xcconfig @@ -0,0 +1,2 @@ +#include "../../Flutter/Flutter-Debug.xcconfig" +#include "Warnings.xcconfig" diff --git a/packages/integration_test/example/macos/Runner/Configs/Release.xcconfig b/packages/integration_test/example/macos/Runner/Configs/Release.xcconfig new file mode 100644 index 0000000000..dff4f49561 --- /dev/null +++ b/packages/integration_test/example/macos/Runner/Configs/Release.xcconfig @@ -0,0 +1,2 @@ +#include "../../Flutter/Flutter-Release.xcconfig" +#include "Warnings.xcconfig" diff --git a/packages/integration_test/example/macos/Runner/Configs/Warnings.xcconfig b/packages/integration_test/example/macos/Runner/Configs/Warnings.xcconfig new file mode 100644 index 0000000000..42bcbf4780 --- /dev/null +++ b/packages/integration_test/example/macos/Runner/Configs/Warnings.xcconfig @@ -0,0 +1,13 @@ +WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings +GCC_WARN_UNDECLARED_SELECTOR = YES +CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES +CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE +CLANG_WARN__DUPLICATE_METHOD_MATCH = YES +CLANG_WARN_PRAGMA_PACK = YES +CLANG_WARN_STRICT_PROTOTYPES = YES +CLANG_WARN_COMMA = YES +GCC_WARN_STRICT_SELECTOR_MATCH = YES +CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES +CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES +GCC_WARN_SHADOW = YES +CLANG_WARN_UNREACHABLE_CODE = YES diff --git a/packages/integration_test/example/macos/Runner/DebugProfile.entitlements b/packages/integration_test/example/macos/Runner/DebugProfile.entitlements new file mode 100644 index 0000000000..dddb8a30c8 --- /dev/null +++ b/packages/integration_test/example/macos/Runner/DebugProfile.entitlements @@ -0,0 +1,12 @@ + + + + + com.apple.security.app-sandbox + + com.apple.security.cs.allow-jit + + com.apple.security.network.server + + + diff --git a/packages/integration_test/example/macos/Runner/Info.plist b/packages/integration_test/example/macos/Runner/Info.plist new file mode 100644 index 0000000000..4789daa6a4 --- /dev/null +++ b/packages/integration_test/example/macos/Runner/Info.plist @@ -0,0 +1,32 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + $(PRODUCT_COPYRIGHT) + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/packages/integration_test/example/macos/Runner/MainFlutterWindow.swift b/packages/integration_test/example/macos/Runner/MainFlutterWindow.swift new file mode 100644 index 0000000000..a97a96274e --- /dev/null +++ b/packages/integration_test/example/macos/Runner/MainFlutterWindow.swift @@ -0,0 +1,19 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import Cocoa +import FlutterMacOS + +class MainFlutterWindow: NSWindow { + override func awakeFromNib() { + let flutterViewController = FlutterViewController.init() + let windowFrame = self.frame + self.contentViewController = flutterViewController + self.setFrame(windowFrame, display: true) + + RegisterGeneratedPlugins(registry: flutterViewController) + + super.awakeFromNib() + } +} diff --git a/packages/integration_test/example/macos/Runner/Release.entitlements b/packages/integration_test/example/macos/Runner/Release.entitlements new file mode 100644 index 0000000000..852fa1a472 --- /dev/null +++ b/packages/integration_test/example/macos/Runner/Release.entitlements @@ -0,0 +1,8 @@ + + + + + com.apple.security.app-sandbox + + + diff --git a/packages/integration_test/example/pubspec.yaml b/packages/integration_test/example/pubspec.yaml new file mode 100644 index 0000000000..cb01dcab73 --- /dev/null +++ b/packages/integration_test/example/pubspec.yaml @@ -0,0 +1,91 @@ +name: integration_test_example +description: Demonstrates how to use the integration_test plugin. +publish_to: 'none' + +environment: + sdk: ">=2.1.0 <3.0.0" + flutter: ">=1.6.7 <2.0.0" + +dependencies: + flutter: + sdk: flutter + + cupertino_icons: 1.0.0 + + characters: 1.1.0-nullsafety.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + collection: 1.15.0-nullsafety.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + meta: 1.3.0-nullsafety.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + typed_data: 1.3.0-nullsafety.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + vector_math: 2.1.0-nullsafety.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + +dev_dependencies: + flutter_test: + sdk: flutter + flutter_driver: + sdk: flutter + integration_test: + sdk: flutter + integration_test_macos: + path: ../integration_test_macos + test: 1.16.0-nullsafety.9 + pedantic: 1.10.0-nullsafety.3 + +# For information on the generic Dart part of this file, see the +# following page: https://dart.dev/tools/pub/pubspec + + _fe_analyzer_shared: 7.0.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + analyzer: 0.39.17 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + archive: 2.0.13 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + args: 1.6.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + async: 2.5.0-nullsafety.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + boolean_selector: 2.1.0-nullsafety.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + charcode: 1.2.0-nullsafety.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + cli_util: 0.2.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + clock: 1.1.0-nullsafety.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + convert: 2.1.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + coverage: 0.14.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + crypto: 2.1.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + csslib: 0.16.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + fake_async: 1.2.0-nullsafety.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + file: 6.0.0-nullsafety.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + glob: 1.2.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + html: 0.14.0+4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + http_multi_server: 2.2.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + http_parser: 3.1.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + io: 0.3.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + js: 0.6.3-nullsafety.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + logging: 0.11.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + matcher: 0.12.10-nullsafety.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + mime: 0.9.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + node_interop: 1.2.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + node_io: 1.1.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + node_preamble: 1.4.12 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + package_config: 1.9.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + path: 1.8.0-nullsafety.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + pool: 1.5.0-nullsafety.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + pub_semver: 1.4.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + shelf: 0.7.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + shelf_packages_handler: 2.0.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + shelf_static: 0.2.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + shelf_web_socket: 0.2.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + source_map_stack_trace: 2.1.0-nullsafety.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + source_maps: 0.10.10-nullsafety.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + source_span: 1.8.0-nullsafety.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + stack_trace: 1.10.0-nullsafety.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + stream_channel: 2.1.0-nullsafety.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + string_scanner: 1.1.0-nullsafety.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + sync_http: 0.2.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + term_glyph: 1.2.0-nullsafety.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + test_api: 0.2.19-nullsafety.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + test_core: 0.3.12-nullsafety.9 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + vm_service: 5.2.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + watcher: 0.9.7+15 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + web_socket_channel: 1.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + webdriver: 2.1.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + webkit_inspection_protocol: 0.7.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + yaml: 2.2.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + +flutter: + uses-material-design: true + +# PUBSPEC CHECKSUM: a89e diff --git a/packages/integration_test/example/test_driver/extended_integration_test.dart b/packages/integration_test/example/test_driver/extended_integration_test.dart new file mode 100644 index 0000000000..0754d70e4e --- /dev/null +++ b/packages/integration_test/example/test_driver/extended_integration_test.dart @@ -0,0 +1,16 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:flutter_driver/flutter_driver.dart'; +import 'package:integration_test/integration_test_driver_extended.dart'; + +Future main() async { + final FlutterDriver driver = await FlutterDriver.connect(); + await integrationDriver( + driver: driver, + onScreenshot: (String screenshotName, List screenshotBytes) async { + return true; + }, + ); +} diff --git a/packages/integration_test/example/test_driver/failure.dart b/packages/integration_test/example/test_driver/failure.dart new file mode 100644 index 0000000000..d297ded7a3 --- /dev/null +++ b/packages/integration_test/example/test_driver/failure.dart @@ -0,0 +1,45 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:integration_test/integration_test.dart'; + +import 'package:integration_test_example/main.dart' as app; + +/// This file is placed in `test_driver/` instead of `integration_test/`, so +/// that the CI tooling of flutter/plugins only uses this together with +/// `failure_test.dart` as the driver. It is only used for testing of +/// `package:integration_test` – do not follow the conventions here if you are a +/// user of `package:integration_test`. + +// Tests the failure behavior of the IntegrationTestWidgetsFlutterBinding +// +// This test fails intentionally! It should be run using a test runner that +// expects failure. +void main() { + IntegrationTestWidgetsFlutterBinding.ensureInitialized(); + + testWidgets('success', (WidgetTester tester) async { + expect(1 + 1, 2); // This should pass + }); + + testWidgets('failure 1', (WidgetTester tester) async { + // Build our app and trigger a frame. + app.main(); + + // Verify that platform version is retrieved. + await expectLater( + find.byWidgetPredicate( + (Widget widget) => + widget is Text && widget.data.startsWith('This should fail'), + ), + findsOneWidget, + ); + }); + + testWidgets('failure 2', (WidgetTester tester) async { + expect(1 + 1, 3); // This should fail + }); +} diff --git a/packages/integration_test/example/test_driver/failure_test.dart b/packages/integration_test/example/test_driver/failure_test.dart new file mode 100644 index 0000000000..88aea930c1 --- /dev/null +++ b/packages/integration_test/example/test_driver/failure_test.dart @@ -0,0 +1,24 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:flutter_driver/flutter_driver.dart'; +import 'package:integration_test/common.dart' as common; +import 'package:test/test.dart' hide TypeMatcher, isInstanceOf; + +/// This file is only used for testing of `package:integration_test` – do not +/// follow the conventions here if you are a user of `package:integration_test`. + +Future main() async { + test('fails gracefully', () async { + final FlutterDriver driver = await FlutterDriver.connect(); + final String jsonResult = + await driver.requestData(null, timeout: const Duration(minutes: 1)); + final common.Response response = common.Response.fromJson(jsonResult); + await driver.close(); + expect( + response.allTestsPassed, + false, + ); + }); +} diff --git a/packages/integration_test/example/test_driver/integration_test.dart b/packages/integration_test/example/test_driver/integration_test.dart new file mode 100644 index 0000000000..600bdc8828 --- /dev/null +++ b/packages/integration_test/example/test_driver/integration_test.dart @@ -0,0 +1,7 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:integration_test/integration_test_driver.dart'; + +Future main() => integrationDriver(); diff --git a/packages/integration_test/example/web/favicon.png b/packages/integration_test/example/web/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..8aaa46ac1ae21512746f852a42ba87e4165dfdd1 GIT binary patch literal 917 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s77>k44ofy`glX=O&z`$AH z5n0T@pr;JNj1^1m%NQ6KBQrxHN+NuHtdjF{^%7I^lT!66atjzhz^1~gBDWwnwIorY zA~z?m*s8)-39P~@uhG~7qCqZhc3d|4;4lG&j~$oK zA@xWG2F9zNE{-7;ld7wO#(qnZWJZzI2E3_xA*Lsx!2?73+ET^w%+}I@67GR zPL~gKB+lnDthp%7_f?t4uW8c8|3WP+WgZ_FE&TA=jOG3EO9#GP7O}Aw)>E_$k#Ij{ zy7GD-^V?e9l7~+mufGc|5hy!fsr=)zztlt_?dh+%eqZG?+EVFvYJGT3%B4l+c?Nxv zA961J%WD)5K5(#z=Uq!-q}j6RjfU+9tC!e#p8CvEH~sU+6WhDDJxnp0o^W94eWCU1 zQd#DyR^MO$Yr>MKOsyrcjGjlI&9nHBnS0EEGw0Y$CX2WHmGZe!`~O@#c5SN5zDu26 zDI4BKt!FtLvCi9OcFDt_gv}BORd*bZl^1SM*A_yFxrSX8ds2x$lS21HT;^ zTCIz7I(nCKmV|Unv7TVUR`#dH$H;AN(TuMbbG%<%3CMZUe|J|QuJuIw1-!H;WNWB?$;ib zdFQ+9g^uhz>as0SX1QKp$Jx0PS=bUhTs~c2!d=hEU?gX@B64~UD6e?B`njxgN@xNA DfL3B_ literal 0 HcmV?d00001 diff --git a/packages/integration_test/example/web/icons/Icon-192.png b/packages/integration_test/example/web/icons/Icon-192.png new file mode 100644 index 0000000000000000000000000000000000000000..b749bfef07473333cf1dd31e9eed89862a5d52aa GIT binary patch literal 5292 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 L>gTe~DWM4f2kRIC literal 0 HcmV?d00001 diff --git a/packages/integration_test/example/web/icons/Icon-512.png b/packages/integration_test/example/web/icons/Icon-512.png new file mode 100644 index 0000000000000000000000000000000000000000..88cfd48dff1169879ba46840804b412fe02fefd6 GIT binary patch literal 8252 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 literal 0 HcmV?d00001 diff --git a/packages/integration_test/example/web/index.html b/packages/integration_test/example/web/index.html new file mode 100644 index 0000000000..fe77e24360 --- /dev/null +++ b/packages/integration_test/example/web/index.html @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + example + + + + + + + + diff --git a/packages/integration_test/example/web/manifest.json b/packages/integration_test/example/web/manifest.json new file mode 100644 index 0000000000..c638001023 --- /dev/null +++ b/packages/integration_test/example/web/manifest.json @@ -0,0 +1,23 @@ +{ + "name": "example", + "short_name": "example", + "start_url": ".", + "display": "minimal-ui", + "background_color": "#0175C2", + "theme_color": "#0175C2", + "description": "A new Flutter project.", + "orientation": "portrait-primary", + "prefer_related_applications": false, + "icons": [ + { + "src": "icons/Icon-192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "icons/Icon-512.png", + "sizes": "512x512", + "type": "image/png" + } + ] +} diff --git a/packages/integration_test/integration_test_macos/CHANGELOG.md b/packages/integration_test/integration_test_macos/CHANGELOG.md new file mode 100644 index 0000000000..ab4bac1a3f --- /dev/null +++ b/packages/integration_test/integration_test_macos/CHANGELOG.md @@ -0,0 +1,11 @@ +## 0.0.2 + +* Renames package to integration_test_macos. + +## 0.0.1+1 + +* Remove Android folder from `e2e_macos`. + +## 0.0.1 + +* Initial release diff --git a/packages/integration_test/integration_test_macos/ios/integration_test_macos.podspec b/packages/integration_test/integration_test_macos/ios/integration_test_macos.podspec new file mode 100644 index 0000000000..8e39e51228 --- /dev/null +++ b/packages/integration_test/integration_test_macos/ios/integration_test_macos.podspec @@ -0,0 +1,21 @@ +# +# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html +# +Pod::Spec.new do |s| + s.name = 'IntegrationTestMacOS' + s.version = '0.0.1' + s.summary = 'No-op implementation of the integration_test desktop plugin to avoid build issues on iOS' + s.description = <<-DESC + No-op implementation of integration to avoid build issues on iOS. + See https://github.com/flutter/flutter/issues/39659 + DESC + s.homepage = 'https://github.com/flutter/plugins/tree/master/packages/integration_test/integration_test_macos' + s.license = { :file => '../LICENSE' } + s.author = { 'Flutter Team' => 'flutter-dev@googlegroups.com' } + s.source = { :path => '.' } + s.source_files = 'Classes/**/*' + s.public_header_files = 'Classes/**/*.h' + s.dependency 'Flutter' + + s.ios.deployment_target = '8.0' +end diff --git a/packages/integration_test/integration_test_macos/macos/Assets/.gitkeep b/packages/integration_test/integration_test_macos/macos/Assets/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/integration_test/integration_test_macos/macos/Classes/IntegrationTestPlugin.swift b/packages/integration_test/integration_test_macos/macos/Classes/IntegrationTestPlugin.swift new file mode 100644 index 0000000000..cb3127f007 --- /dev/null +++ b/packages/integration_test/integration_test_macos/macos/Classes/IntegrationTestPlugin.swift @@ -0,0 +1,26 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import FlutterMacOS + +public class IntegrationTestPlugin: NSObject, FlutterPlugin { + + public static func register(with registrar: FlutterPluginRegistrar) { + let channel = FlutterMethodChannel( + name: "plugins.flutter.io/integration_test", + binaryMessenger: registrar.messenger) + + let instance = IntegrationTestPlugin() + registrar.addMethodCallDelegate(instance, channel: channel) + } + + public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { + switch call.method { + case "allTestsFinished": + result(nil) + default: + result(FlutterMethodNotImplemented) + } + } +} diff --git a/packages/integration_test/integration_test_macos/macos/integration_test_macos.podspec b/packages/integration_test/integration_test_macos/macos/integration_test_macos.podspec new file mode 100644 index 0000000000..5f43e61509 --- /dev/null +++ b/packages/integration_test/integration_test_macos/macos/integration_test_macos.podspec @@ -0,0 +1,20 @@ +# +# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html +# +Pod::Spec.new do |s| + s.name = 'IntegrationTestMacOS' + s.version = '0.0.1' + s.summary = 'Adapter for integration tests.' + s.description = <<-DESC +Runs tests that use the flutter_test API as integration tests on macOS. + DESC + s.homepage = 'https://github.com/flutter/plugins/tree/master/packages/integration_test/integration_test_macos' + s.license = { :type => 'BSD', :file => '../LICENSE' } + s.author = { 'Flutter Team' => 'flutter-dev@googlegroups.com' } + s.source = { :http => 'https://github.com/flutter/plugins/tree/master/packages/integration_test' } + s.source_files = 'Classes/**/*' + s.dependency 'FlutterMacOS' + + s.platform = :osx, '10.11' + s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES' } +end diff --git a/packages/integration_test/integration_test_macos/pubspec.yaml b/packages/integration_test/integration_test_macos/pubspec.yaml new file mode 100644 index 0000000000..c6096680fe --- /dev/null +++ b/packages/integration_test/integration_test_macos/pubspec.yaml @@ -0,0 +1,29 @@ +name: integration_test_macos +description: Desktop implementation of integration_test plugin +version: 0.0.1+1 +author: Flutter Team +homepage: https://github.com/flutter/plugins/tree/master/packages/integration_test/integration_test_macos + +flutter: + plugin: + platforms: + macos: + pluginClass: IntegrationTestPlugin + +environment: + sdk: ">=2.1.0 <3.0.0" + +dependencies: + flutter: + sdk: flutter + + characters: 1.1.0-nullsafety.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + collection: 1.15.0-nullsafety.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + meta: 1.3.0-nullsafety.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + typed_data: 1.3.0-nullsafety.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + vector_math: 2.1.0-nullsafety.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + +dev_dependencies: + pedantic: 1.10.0-nullsafety.3 + +# PUBSPEC CHECKSUM: fd54 diff --git a/packages/integration_test/ios/.gitignore b/packages/integration_test/ios/.gitignore new file mode 100644 index 0000000000..aa479fd3ce --- /dev/null +++ b/packages/integration_test/ios/.gitignore @@ -0,0 +1,37 @@ +.idea/ +.vagrant/ +.sconsign.dblite +.svn/ + +.DS_Store +*.swp +profile + +DerivedData/ +build/ +GeneratedPluginRegistrant.h +GeneratedPluginRegistrant.m + +.generated/ + +*.pbxuser +*.mode1v3 +*.mode2v3 +*.perspectivev3 + +!default.pbxuser +!default.mode1v3 +!default.mode2v3 +!default.perspectivev3 + +xcuserdata + +*.moved-aside + +*.pyc +*sync/ +Icon? +.tags* + +/Flutter/Generated.xcconfig +/Flutter/flutter_export_environment.sh \ No newline at end of file diff --git a/packages/integration_test/ios/Assets/.gitkeep b/packages/integration_test/ios/Assets/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/integration_test/ios/Classes/IntegrationTestIosTest.h b/packages/integration_test/ios/Classes/IntegrationTestIosTest.h new file mode 100644 index 0000000000..5a127dab11 --- /dev/null +++ b/packages/integration_test/ios/Classes/IntegrationTestIosTest.h @@ -0,0 +1,26 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import + +@interface IntegrationTestIosTest : NSObject + +- (BOOL)testIntegrationTest:(NSString **)testResult; + +@end + +#define INTEGRATION_TEST_IOS_RUNNER(__test_class) \ + @interface __test_class : XCTestCase \ + @end \ + \ + @implementation __test_class \ + \ + -(void)testIntegrationTest { \ + NSString *testResult; \ + IntegrationTestIosTest *integrationTestIosTest = [[IntegrationTestIosTest alloc] init]; \ + BOOL testPass = [integrationTestIosTest testIntegrationTest:&testResult]; \ + XCTAssertTrue(testPass, @"%@", testResult); \ + } \ + \ + @end diff --git a/packages/integration_test/ios/Classes/IntegrationTestIosTest.m b/packages/integration_test/ios/Classes/IntegrationTestIosTest.m new file mode 100644 index 0000000000..c989f8e053 --- /dev/null +++ b/packages/integration_test/ios/Classes/IntegrationTestIosTest.m @@ -0,0 +1,47 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "IntegrationTestIosTest.h" +#import "IntegrationTestPlugin.h" + +@implementation IntegrationTestIosTest + +- (BOOL)testIntegrationTest:(NSString **)testResult { + IntegrationTestPlugin *integrationTestPlugin = [IntegrationTestPlugin instance]; + UIViewController *rootViewController = + [[[[UIApplication sharedApplication] delegate] window] rootViewController]; + if (![rootViewController isKindOfClass:[FlutterViewController class]]) { + NSLog(@"expected FlutterViewController as rootViewController."); + return NO; + } + FlutterViewController *flutterViewController = (FlutterViewController *)rootViewController; + [integrationTestPlugin setupChannels:flutterViewController.engine.binaryMessenger]; + while (!integrationTestPlugin.testResults) { + CFRunLoopRunInMode(kCFRunLoopDefaultMode, 1.f, NO); + } + NSDictionary *testResults = integrationTestPlugin.testResults; + NSMutableArray *passedTests = [NSMutableArray array]; + NSMutableArray *failedTests = [NSMutableArray array]; + NSLog(@"==================== Test Results ====================="); + for (NSString *test in testResults.allKeys) { + NSString *result = testResults[test]; + if ([result isEqualToString:@"success"]) { + NSLog(@"%@ passed.", test); + [passedTests addObject:test]; + } else { + NSLog(@"%@ failed: %@", test, result); + [failedTests addObject:test]; + } + } + NSLog(@"================== Test Results End ===================="); + BOOL testPass = failedTests.count == 0; + if (!testPass && testResult) { + *testResult = + [NSString stringWithFormat:@"Detected failed integration test(s) %@ among %@", + failedTests.description, testResults.allKeys.description]; + } + return testPass; +} + +@end diff --git a/packages/integration_test/ios/Classes/IntegrationTestPlugin.h b/packages/integration_test/ios/Classes/IntegrationTestPlugin.h new file mode 100644 index 0000000000..d73246a6b9 --- /dev/null +++ b/packages/integration_test/ios/Classes/IntegrationTestPlugin.h @@ -0,0 +1,29 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** A Flutter plugin that's responsible for communicating the test results back + * to iOS XCTest. */ +@interface IntegrationTestPlugin : NSObject + +/** + * Test results that are sent from Dart when integration test completes. Before the + * completion, it is + * @c nil. + */ +@property(nonatomic, readonly, nullable) NSDictionary *testResults; + +/** Fetches the singleton instance of the plugin. */ ++ (IntegrationTestPlugin *)instance; + +- (void)setupChannels:(id)binaryMessenger; + +- (instancetype)init NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END diff --git a/packages/integration_test/ios/Classes/IntegrationTestPlugin.m b/packages/integration_test/ios/Classes/IntegrationTestPlugin.m new file mode 100644 index 0000000000..8d8f8ae47f --- /dev/null +++ b/packages/integration_test/ios/Classes/IntegrationTestPlugin.m @@ -0,0 +1,58 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "IntegrationTestPlugin.h" + +static NSString *const kIntegrationTestPluginChannel = @"plugins.flutter.io/integration_test"; +static NSString *const kMethodTestFinished = @"allTestsFinished"; + +@interface IntegrationTestPlugin () + +@property(nonatomic, readwrite) NSDictionary *testResults; + +@end + +@implementation IntegrationTestPlugin { + NSDictionary *_testResults; +} + ++ (IntegrationTestPlugin *)instance { + static dispatch_once_t onceToken; + static IntegrationTestPlugin *sInstance; + dispatch_once(&onceToken, ^{ + sInstance = [[IntegrationTestPlugin alloc] initForRegistration]; + }); + return sInstance; +} + +- (instancetype)initForRegistration { + return [super init]; +} + ++ (void)registerWithRegistrar:(NSObject *)registrar { + // No initialization happens here because of the way XCTest loads the testing + // bundles. Setup on static variables can be disregarded when a new static + // instance of IntegrationTestPlugin is allocated when the bundle is reloaded. + // See also: https://github.com/flutter/plugins/pull/2465 +} + +- (void)setupChannels:(id)binaryMessenger { + FlutterMethodChannel *channel = + [FlutterMethodChannel methodChannelWithName:kIntegrationTestPluginChannel + binaryMessenger:binaryMessenger]; + [channel setMethodCallHandler:^(FlutterMethodCall *call, FlutterResult result) { + [self handleMethodCall:call result:result]; + }]; +} + +- (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result { + if ([kMethodTestFinished isEqual:call.method]) { + self.testResults = call.arguments[@"results"]; + result(nil); + } else { + result(FlutterMethodNotImplemented); + } +} + +@end diff --git a/packages/integration_test/ios/integration_test.podspec b/packages/integration_test/ios/integration_test.podspec new file mode 100644 index 0000000000..824a491f12 --- /dev/null +++ b/packages/integration_test/ios/integration_test.podspec @@ -0,0 +1,20 @@ +# +# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html +# +Pod::Spec.new do |s| + s.name = 'integration_test' + s.version = '0.0.1' + s.summary = 'Adapter for integration tests.' + s.description = <<-DESC +Runs tests that use the flutter_test API as integration tests. + DESC + s.homepage = 'https://github.com/flutter/plugins/tree/master/packages/integration_test' + s.license = { :type => 'BSD', :file => '../LICENSE' } + s.author = { 'Flutter Team' => 'flutter-dev@googlegroups.com' } + s.source = { :http => 'https://github.com/flutter/plugins/tree/master/packages/integration_test' } + s.source_files = 'Classes/**/*' + s.public_header_files = 'Classes/**/*.h' + s.dependency 'Flutter' + s.platform = :ios, '8.0' + s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'VALID_ARCHS[sdk=iphonesimulator*]' => 'x86_64' } +end diff --git a/packages/integration_test/lib/_callback_io.dart b/packages/integration_test/lib/_callback_io.dart new file mode 100644 index 0000000000..c5c9645442 --- /dev/null +++ b/packages/integration_test/lib/_callback_io.dart @@ -0,0 +1,62 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'common.dart'; + +/// The dart:io implementation of [CallbackManager]. +/// +/// See also: +/// +/// * `_callback_web.dart`, which has the dart:html implementation +CallbackManager get callbackManager => _singletonCallbackManager; + +/// IOCallbackManager singleton. +final IOCallbackManager _singletonCallbackManager = IOCallbackManager(); + +/// Manages communication between `integration_tests` and the `driver_tests`. +/// +/// This is the dart:io implementation. +class IOCallbackManager implements CallbackManager { + @override + Future> callback( + Map params, IntegrationTestResults testRunner) async { + final String command = params['command']; + Map response; + switch (command) { + case 'request_data': + final bool allTestsPassed = await testRunner.allTestsPassed.future; + response = { + 'message': allTestsPassed + ? Response.allTestsPassed(data: testRunner.reportData).toJson() + : Response.someTestsFailed( + testRunner.failureMethodsDetails, + data: testRunner.reportData, + ).toJson(), + }; + break; + case 'get_health': + response = {'status': 'ok'}; + break; + default: + throw UnimplementedError('$command is not implemented'); + } + return { + 'isError': false, + 'response': response, + }; + } + + @override + void cleanup() { + // no-op. + // Add any IO platform specific Completer/Future cleanups to here if any + // comes up in the future. For example: `WebCallbackManager.cleanup`. + } + + @override + Future takeScreenshot(String screenshot) { + throw UnimplementedError( + 'Screenshots are not implemented on this platform'); + } +} diff --git a/packages/integration_test/lib/_callback_web.dart b/packages/integration_test/lib/_callback_web.dart new file mode 100644 index 0000000000..b13181b4be --- /dev/null +++ b/packages/integration_test/lib/_callback_web.dart @@ -0,0 +1,169 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:async'; + +import 'package:flutter_test/flutter_test.dart'; + +import 'common.dart'; + +/// The dart:html implementation of [CallbackManager]. +/// +/// See also: +/// +/// * `_callback_io.dart`, which has the dart:io implementation +CallbackManager get callbackManager => _singletonWebDriverCommandManager; + +/// WebDriverCommandManager singleton. +final WebCallbackManager _singletonWebDriverCommandManager = + WebCallbackManager(); + +/// Manages communication between `integration_tests` and the `driver_tests`. +/// +/// Along with responding to callbacks from the driver side this calls enables +/// usage of Web Driver commands by sending [WebDriverCommand]s to driver side. +/// +/// Tests can execute an Web Driver commands such as `screenshot` using browsers' +/// WebDriver APIs. +/// +/// See: https://www.w3.org/TR/webdriver/ +class WebCallbackManager implements CallbackManager { + /// App side tests will put the command requests from WebDriver to this pipe. + Completer _webDriverCommandPipe = + Completer(); + + /// Updated when WebDriver completes the request by the test method. + /// + /// For example, a test method will ask for a screenshot by calling + /// `takeScreenshot`. When this screenshot is taken [_driverCommandComplete] + /// will complete. + Completer _driverCommandComplete = Completer(); + + /// Takes screenshot using WebDriver screenshot command. + /// + /// Only works on Web when tests are run via `flutter driver` command. + /// + /// See: https://www.w3.org/TR/webdriver/#screen-capture. + @override + Future takeScreenshot(String screenshotName) async { + await _sendWebDriverCommand(WebDriverCommand.screenshot(screenshotName)); + } + + Future _sendWebDriverCommand(WebDriverCommand command) async { + try { + _webDriverCommandPipe.complete(command); + final bool awaitCommand = await _driverCommandComplete.future; + if (!awaitCommand) { + throw Exception( + 'Web Driver Command ${command.type} failed while waiting for ' + 'driver side'); + } + } catch (exception) { + throw Exception('Web Driver Command failed: ${command.type} with ' + 'exception $exception'); + } finally { + // Reset the completer. + _driverCommandComplete = Completer(); + } + } + + /// The callback function to response the driver side input. + /// + /// Provides a handshake mechanism for executing [WebDriverCommand]s on the + /// driver side. + @override + Future> callback( + Map params, IntegrationTestResults testRunner) async { + final String command = params['command']; + Map response; + switch (command) { + case 'request_data': + return params['message'] == null + ? _requestData(testRunner) + : _requestDataWithMessage(params['message'], testRunner); + break; + case 'get_health': + response = {'status': 'ok'}; + break; + default: + throw UnimplementedError('$command is not implemented'); + } + return { + 'isError': false, + 'response': response, + }; + } + + Future> _requestDataWithMessage( + String extraMessage, IntegrationTestResults testRunner) async { + Map response; + // Driver side tests' status is added as an extra message. + final DriverTestMessage message = + DriverTestMessage.fromString(extraMessage); + // If driver side tests are pending send the first command in the + // `commandPipe` to the tests. + if (message.isPending) { + final WebDriverCommand command = await _webDriverCommandPipe.future; + switch (command.type) { + case WebDriverCommandType.screenshot: + final Map data = Map.from(command.values); + data.addAll( + WebDriverCommand.typeToMap(WebDriverCommandType.screenshot)); + response = { + 'message': Response.webDriverCommand(data: data).toJson(), + }; + break; + case WebDriverCommandType.noop: + final Map data = {}; + data.addAll(WebDriverCommand.typeToMap(WebDriverCommandType.noop)); + response = { + 'message': Response.webDriverCommand(data: data).toJson(), + }; + break; + default: + throw UnimplementedError('${command.type} is not implemented'); + } + } else { + final Map data = {}; + data.addAll(WebDriverCommand.typeToMap(WebDriverCommandType.ack)); + response = { + 'message': Response.webDriverCommand(data: data).toJson(), + }; + _driverCommandComplete.complete(message.isSuccess); + _webDriverCommandPipe = Completer(); + } + return { + 'isError': false, + 'response': response, + }; + } + + Future> _requestData(IntegrationTestResults testRunner) async { + final bool allTestsPassed = await testRunner.allTestsPassed.future; + final Map response = { + 'message': allTestsPassed + ? Response.allTestsPassed(data: testRunner.reportData).toJson() + : Response.someTestsFailed( + testRunner.failureMethodsDetails, + data: testRunner.reportData, + ).toJson(), + }; + return { + 'isError': false, + 'response': response, + }; + } + + @override + void cleanup() { + if (!_webDriverCommandPipe.isCompleted) { + _webDriverCommandPipe + .complete(Future.value(WebDriverCommand.noop())); + } + + if (!_driverCommandComplete.isCompleted) { + _driverCommandComplete.complete(Future.value(false)); + } + } +} diff --git a/packages/integration_test/lib/_extension_io.dart b/packages/integration_test/lib/_extension_io.dart new file mode 100644 index 0000000000..cf0c91cfc9 --- /dev/null +++ b/packages/integration_test/lib/_extension_io.dart @@ -0,0 +1,13 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/// The dart:io implementation of [registerWebServiceExtension]. +/// +/// See also: +/// +/// * `_extension_web.dart`, which has the dart:html implementation +void registerWebServiceExtension( + Future> Function(Map) call) { + throw UnsupportedError('Use registerServiceExtension instead'); +} diff --git a/packages/integration_test/lib/_extension_web.dart b/packages/integration_test/lib/_extension_web.dart new file mode 100644 index 0000000000..01f1dac1b4 --- /dev/null +++ b/packages/integration_test/lib/_extension_web.dart @@ -0,0 +1,32 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:async'; +import 'dart:convert'; +import 'dart:html' as html; +import 'dart:js'; +import 'dart:js_util' as js_util; + +/// The dart:html implementation of [registerWebServiceExtension]. +/// +/// Registers Web Service Extension for Flutter Web application. +/// +/// window.$flutterDriver will be called by Flutter Web Driver to process +/// Flutter command. +/// +/// See also: +/// +/// * `_extension_io.dart`, which has the dart:io implementation +void registerWebServiceExtension( + Future> Function(Map) call) { + js_util.setProperty(html.window, r'$flutterDriver', + allowInterop((dynamic message) async { + // ignore: undefined_function, undefined_identifier + final Map params = Map.from( + jsonDecode(message as String) as Map); + final Map result = + Map.from(await call(params)); + context[r'$flutterDriverResult'] = json.encode(result); + })); +} diff --git a/packages/integration_test/lib/common.dart b/packages/integration_test/lib/common.dart new file mode 100644 index 0000000000..23a9081e0e --- /dev/null +++ b/packages/integration_test/lib/common.dart @@ -0,0 +1,298 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:async'; +import 'dart:convert'; + +/// Classes shared between `integration_test.dart` and `flutter drive` based +/// adoptor (ex: `integration_test_driver.dart`). + +/// An object sent from integration_test back to the Flutter Driver in response to +/// `request_data` command. +class Response { + /// Constructor to use for positive response. + Response.allTestsPassed({this.data}) + : _allTestsPassed = true, + _failureDetails = null; + + /// Constructor for failure response. + Response.someTestsFailed(this._failureDetails, {this.data}) + : _allTestsPassed = false; + + /// Constructor for failure response. + Response.toolException({String ex}) + : _allTestsPassed = false, + _failureDetails = [Failure('ToolException', ex)]; + + /// Constructor for web driver commands response. + Response.webDriverCommand({this.data}) + : _allTestsPassed = false, + _failureDetails = null; + + final List _failureDetails; + + final bool _allTestsPassed; + + /// The extra information to be added along side the test result. + Map data; + + /// Whether the test ran successfully or not. + bool get allTestsPassed => _allTestsPassed; + + /// If the result are failures get the formatted details. + String get formattedFailureDetails => + _allTestsPassed ? '' : formatFailures(_failureDetails); + + /// Failure details as a list. + List get failureDetails => _failureDetails; + + /// Serializes this message to a JSON map. + String toJson() => json.encode({ + 'result': allTestsPassed.toString(), + 'failureDetails': _failureDetailsAsString(), + if (data != null) 'data': data + }); + + /// Deserializes the result from JSON. + static Response fromJson(String source) { + final Map responseJson = json.decode(source) as Map; + if (responseJson['result'] as String == 'true') { + return Response.allTestsPassed(data: responseJson['data'] as Map); + } else { + return Response.someTestsFailed( + _failureDetailsFromJson(responseJson['failureDetails'] as List), + data: responseJson['data'] as Map, + ); + } + } + + /// Method for formatting the test failures' details. + String formatFailures(List failureDetails) { + if (failureDetails.isEmpty) { + return ''; + } + + final StringBuffer sb = StringBuffer(); + int failureCount = 1; + for (final Failure failure in failureDetails) { + sb.writeln('Failure in method: ${failure.methodName}'); + sb.writeln(failure.details); + sb.writeln('end of failure ${failureCount.toString()}\n\n'); + failureCount++; + } + return sb.toString(); + } + + /// Create a list of Strings from [_failureDetails]. + List _failureDetailsAsString() { + final List list = []; + if (_failureDetails == null || _failureDetails.isEmpty) { + return list; + } + + for (final Failure failure in _failureDetails) { + list.add(failure.toJson()); + } + + return list; + } + + /// Creates a [Failure] list using a json response. + static List _failureDetailsFromJson(List list) { + return list.map((dynamic s) { + return Failure.fromJsonString(s as String); + }).toList(); + } +} + +/// Representing a failure includes the method name and the failure details. +class Failure { + /// Constructor requiring all fields during initialization. + Failure(this.methodName, this.details); + + /// The name of the test method which failed. + final String methodName; + + /// The details of the failure such as stack trace. + final String details; + + /// Serializes the object to JSON. + String toJson() { + return json.encode({ + 'methodName': methodName, + 'details': details, + }); + } + + @override + String toString() => toJson(); + + /// Decode a JSON string to create a Failure object. + static Failure fromJsonString(String jsonString) { + final Map failure = json.decode(jsonString) as Map; + return Failure(failure['methodName'] as String, failure['details'] as String); + } +} + +/// Message used to communicate between app side tests and driver tests. +/// +/// Not all `integration_tests` use this message. They are only used when app +/// side tests are sending [WebDriverCommand]s to the driver side. +/// +/// These messages are used for the handshake since they carry information on +/// the driver side test such as: status pending or tests failed. +class DriverTestMessage { + /// When tests are failed on the driver side. + DriverTestMessage.error() + : _isSuccess = false, + _isPending = false; + + /// When driver side is waiting on [WebDriverCommand]s to be sent from the + /// app side. + DriverTestMessage.pending() + : _isSuccess = false, + _isPending = true; + + /// When driver side successfully completed executing the [WebDriverCommand]. + DriverTestMessage.complete() + : _isSuccess = true, + _isPending = false; + + final bool _isSuccess; + final bool _isPending; + + // /// Status of this message. + // /// + // /// The status will be use to notify `integration_test` of driver side's + // /// state. + // String get status => _status; + + /// Has the command completed successfully by the driver. + bool get isSuccess => _isSuccess; + + /// Is the driver waiting for a command. + bool get isPending => _isPending; + + /// Depending on the values of [isPending] and [isSuccess], returns a string + /// to represent the [DriverTestMessage]. + /// + /// Used as an alternative method to converting the object to json since + /// [RequestData] is only accepting string as `message`. + @override + String toString() { + if (isPending) { + return 'pending'; + } else if (isSuccess) { + return 'complete'; + } else { + return 'error'; + } + } + + /// Return a DriverTestMessage depending on `status`. + static DriverTestMessage fromString(String status) { + switch (status) { + case 'error': + return DriverTestMessage.error(); + case 'pending': + return DriverTestMessage.pending(); + case 'complete': + return DriverTestMessage.complete(); + default: + throw StateError('This type of status does not exist: $status'); + } + } +} + +/// Types of different WebDriver commands that can be used in web integration +/// tests. +/// +/// These commands are either commands that WebDriver can execute or used +/// for the communication between `integration_test` and the driver test. +enum WebDriverCommandType { + /// Acknowlegement for the previously sent message. + ack, + + /// No further WebDriver commands is requested by the app-side tests. + noop, + + /// Asking WebDriver to take a screenshot of the Web page. + screenshot, +} + +/// Command for WebDriver to execute. +/// +/// Only works on Web when tests are run via `flutter driver` command. +/// +/// See: https://www.w3.org/TR/webdriver/ +class WebDriverCommand { + /// Constructor for [WebDriverCommandType.noop] command. + WebDriverCommand.noop() + : type = WebDriverCommandType.noop, + values = {}; + + /// Constructor for [WebDriverCommandType.noop] screenshot. + WebDriverCommand.screenshot(String screenshotName) + : type = WebDriverCommandType.screenshot, + values = {'screenshot_name': screenshotName}; + + /// Type of the [WebDriverCommand]. + /// + /// Currently the only command that triggers a WebDriver API is `screenshot`. + /// + /// There are also `ack` and `noop` commands defined to manage the handshake + /// during the communication. + final WebDriverCommandType type; + + /// Used for adding extra values to the commands such as file name for + /// `screenshot`. + final Map values; + + /// Util method for converting [WebDriverCommandType] to a map entry. + /// + /// Used for converting messages to json format. + static Map typeToMap(WebDriverCommandType type) => { + 'web_driver_command': '$type', + }; +} + +/// Template methods each class that responses the driver side inputs must +/// implement. +/// +/// Depending on the platform the communication between `integration_tests` and +/// the `driver_tests` can be different. +/// +/// For the web implementation [WebCallbackManager]. +/// For the io implementation [IOCallbackManager]. +abstract class CallbackManager { + /// The callback function to response the driver side input. + Future> callback( + Map params, IntegrationTestResults testRunner); + + /// Request to take a screenshot of the application. + Future takeScreenshot(String screenshot); + + /// Cleanup and completers or locks used during the communication. + void cleanup(); +} + +/// Interface that surfaces test results of integration tests. +/// +/// Implemented by [IntegrationTestWidgetsFlutterBinding]s. +/// +/// Any class which needs to access the test results but do not want to create +/// a cyclic dependency [IntegrationTestWidgetsFlutterBinding]s can use this +/// interface. Example [CallbackManager]. +abstract class IntegrationTestResults { + /// Stores failure details. + /// + /// Failed test method's names used as key. + List get failureMethodsDetails; + + /// The extra data for the reported result. + Map get reportData; + + /// Whether all the test methods completed succesfully. + Completer get allTestsPassed; +} diff --git a/packages/integration_test/lib/integration_test.dart b/packages/integration_test/lib/integration_test.dart new file mode 100644 index 0000000000..de42574325 --- /dev/null +++ b/packages/integration_test/lib/integration_test.dart @@ -0,0 +1,322 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:async'; +import 'dart:developer' as developer; +import 'dart:ui'; + +import 'package:flutter/rendering.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter/widgets.dart'; +import 'package:vm_service/vm_service.dart' as vm; +import 'package:vm_service/vm_service_io.dart' as vm_io; + +import '_callback_io.dart' if (dart.library.html) '_callback_web.dart' as driver_actions; +import '_extension_io.dart' if (dart.library.html) '_extension_web.dart'; +import 'common.dart'; + +const String _success = 'success'; + +/// A subclass of [LiveTestWidgetsFlutterBinding] that reports tests results +/// on a channel to adapt them to native instrumentation test format. +class IntegrationTestWidgetsFlutterBinding extends LiveTestWidgetsFlutterBinding implements IntegrationTestResults { + /// Sets up a listener to report that the tests are finished when everything is + /// torn down. + IntegrationTestWidgetsFlutterBinding() { + // TODO(jackson): Report test results as they arrive + tearDownAll(() async { + try { + // For web integration tests we are not using the + // `plugins.flutter.io/integration_test`. Mark the tests as complete + // before invoking the channel. + if (kIsWeb) { + if (!_allTestsPassed.isCompleted) { + _allTestsPassed.complete(true); + } + } + callbackManager.cleanup(); + await _channel.invokeMethod( + 'allTestsFinished', + { + 'results': results.map((String name, Object result) { + if (result is Failure) { + return MapEntry(name, result.details); + } + return MapEntry(name, result); + }) + }, + ); + } on MissingPluginException { + print('Warning: integration_test test plugin was not detected.'); + } + if (!_allTestsPassed.isCompleted) { + _allTestsPassed.complete(true); + } + }); + + // TODO(jackson): Report the results individually instead of all at once + // See https://github.com/flutter/flutter/issues/38985 + final TestExceptionReporter oldTestExceptionReporter = reportTestException; + reportTestException = + (FlutterErrorDetails details, String testDescription) { + results[testDescription] = Failure(testDescription, details.toString()); + if (!_allTestsPassed.isCompleted) { + _allTestsPassed.complete(false); + } + oldTestExceptionReporter(details, testDescription); + }; + } + + @override + bool get overrideHttpClient => false; + + @override + bool get registerTestTextInput => false; + + Size _surfaceSize; + + // This flag is used to print warning messages when tracking performance + // under debug mode. + static bool _firstRun = false; + + /// Artificially changes the surface size to `size` on the Widget binding, + /// then flushes microtasks. + /// + /// Set to null to use the default surface size. + @override + Future setSurfaceSize(Size size) { + return TestAsyncUtils.guard(() async { + assert(inTest); + if (_surfaceSize == size) { + return; + } + _surfaceSize = size; + handleMetricsChanged(); + }); + } + + @override + ViewConfiguration createViewConfiguration() { + final double devicePixelRatio = window.devicePixelRatio; + final Size size = _surfaceSize ?? window.physicalSize / devicePixelRatio; + return TestViewConfiguration( + size: size, + window: window, + ); + } + + @override + Completer get allTestsPassed => _allTestsPassed; + final Completer _allTestsPassed = Completer(); + + @override + List get failureMethodsDetails => _failures; + + /// Similar to [WidgetsFlutterBinding.ensureInitialized]. + /// + /// Returns an instance of the [IntegrationTestWidgetsFlutterBinding], creating and + /// initializing it if necessary. + static WidgetsBinding ensureInitialized() { + if (WidgetsBinding.instance == null) { + IntegrationTestWidgetsFlutterBinding(); + } + assert(WidgetsBinding.instance is IntegrationTestWidgetsFlutterBinding); + return WidgetsBinding.instance; + } + + static const MethodChannel _channel = + MethodChannel('plugins.flutter.io/integration_test'); + + /// Test results that will be populated after the tests have completed. + /// + /// Keys are the test descriptions, and values are either [_success] or + /// a [Failure]. + @visibleForTesting + Map results = {}; + + List get _failures => results.values.whereType().toList(); + + /// The extra data for the reported result. + /// + /// The values in `reportData` must be json-serializable objects or `null`. + /// If it's `null`, no extra data is attached to the result. + /// + /// The default value is `null`. + @override + Map reportData; + + /// Manages callbacks received from driver side and commands send to driver + /// side. + final CallbackManager callbackManager = driver_actions.callbackManager; + + /// Taking a screenshot. + /// + /// Called by test methods. Implementation differs for each platform. + Future takeScreenshot(String screenshotName) async { + await callbackManager.takeScreenshot(screenshotName); + } + + /// The callback function to response the driver side input. + @visibleForTesting + Future> callback(Map params) async { + return await callbackManager.callback( + params, this /* as IntegrationTestResults */); + } + + // Emulates the Flutter driver extension, returning 'pass' or 'fail'. + @override + void initServiceExtensions() { + super.initServiceExtensions(); + + if (kIsWeb) { + registerWebServiceExtension(callback); + } + + registerServiceExtension(name: 'driver', callback: callback); + } + + @override + Future runTest( + Future testBody(), + VoidCallback invariantTester, { + String description = '', + Duration timeout, + }) async { + await super.runTest( + testBody, + invariantTester, + description: description, + timeout: timeout, + ); + results[description] ??= _success; + } + + vm.VmService _vmService; + + /// Initialize the [vm.VmService] settings for the timeline. + @visibleForTesting + Future enableTimeline({ + List streams = const ['all'], + @visibleForTesting vm.VmService vmService, + }) async { + assert(streams != null); + assert(streams.isNotEmpty); + if (vmService != null) { + _vmService = vmService; + } + if (_vmService == null) { + final developer.ServiceProtocolInfo info = + await developer.Service.getInfo(); + assert(info.serverUri != null); + _vmService = await vm_io.vmServiceConnectUri( + 'ws://localhost:${info.serverUri.port}${info.serverUri.path}ws', + ); + } + await _vmService.setVMTimelineFlags(streams); + } + + /// Runs [action] and returns a [vm.Timeline] trace for it. + /// + /// Waits for the `Future` returned by [action] to complete prior to stopping + /// the trace. + /// + /// The `streams` parameter limits the recorded timeline event streams to only + /// the ones listed. By default, all streams are recorded. + /// See `timeline_streams` in + /// [Dart-SDK/runtime/vm/timeline.cc](https://github.com/dart-lang/sdk/blob/master/runtime/vm/timeline.cc) + /// + /// If [retainPriorEvents] is true, retains events recorded prior to calling + /// [action]. Otherwise, prior events are cleared before calling [action]. By + /// default, prior events are cleared. + Future traceTimeline( + Future action(), { + List streams = const ['all'], + bool retainPriorEvents = false, + }) async { + await enableTimeline(streams: streams); + if (retainPriorEvents) { + await action(); + return await _vmService.getVMTimeline(); + } + + await _vmService.clearVMTimeline(); + final vm.Timestamp startTime = await _vmService.getVMTimelineMicros(); + await action(); + final vm.Timestamp endTime = await _vmService.getVMTimelineMicros(); + return await _vmService.getVMTimeline( + timeOriginMicros: startTime.timestamp, + timeExtentMicros: endTime.timestamp, + ); + } + + /// This is a convenience wrap of [traceTimeline] and send the result back to + /// the host for the [flutter_driver] style tests. + /// + /// This records the timeline during `action` and adds the result to + /// [reportData] with `reportKey`. The [reportData] contains extra information + /// from the test other than test success/fail. It will be passed back to the + /// host and be processed by the [ResponseDataCallback] defined in + /// [integration_test_driver.integrationDriver]. By default it will be written + /// to `build/integration_response_data.json` with the key `timeline`. + /// + /// For tests with multiple calls of this method, `reportKey` needs to be a + /// unique key, otherwise the later result will override earlier one. + /// + /// The `streams` and `retainPriorEvents` parameters are passed as-is to + /// [traceTimeline]. + Future traceAction( + Future action(), { + List streams = const ['all'], + bool retainPriorEvents = false, + String reportKey = 'timeline', + }) async { + final vm.Timeline timeline = await traceTimeline( + action, + streams: streams, + retainPriorEvents: retainPriorEvents, + ); + reportData ??= {}; + reportData[reportKey] = timeline.toJson(); + } + + /// Watches the [FrameTiming] during `action` and report it to the binding + /// with key `reportKey`. + /// + /// This can be used to implement performance tests previously using + /// [traceAction] and [TimelineSummary] from [flutter_driver] + Future watchPerformance( + Future action(), { + String reportKey = 'performance', + }) async { + assert(() { + if (_firstRun) { + debugPrint(kDebugWarning); + _firstRun = false; + } + return true; + }()); + + // The engine could batch FrameTimings and send them only once per second. + // Delay for a sufficient time so either old FrameTimings are flushed and not + // interfering our measurements here, or new FrameTimings are all reported. + // TODO(CareF): remove this when flush FrameTiming is readly in engine. + // See https://github.com/flutter/flutter/issues/64808 + // and https://github.com/flutter/flutter/issues/67593 + Future delayForFrameTimings() => Future.delayed(const Duration(seconds: 2)); + + await delayForFrameTimings(); // flush old FrameTimings + final List frameTimings = []; + final TimingsCallback watcher = frameTimings.addAll; + addTimingsCallback(watcher); + await action(); + await delayForFrameTimings(); // make sure all FrameTimings are reported + removeTimingsCallback(watcher); + final FrameTimingSummarizer frameTimes = + FrameTimingSummarizer(frameTimings); + reportData ??= {}; + reportData[reportKey] = frameTimes.summary; + } +} diff --git a/packages/integration_test/lib/integration_test_driver.dart b/packages/integration_test/lib/integration_test_driver.dart new file mode 100644 index 0000000000..783e1af6c1 --- /dev/null +++ b/packages/integration_test/lib/integration_test_driver.dart @@ -0,0 +1,91 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:async'; +import 'dart:convert'; +import 'dart:io'; + +import 'package:flutter_driver/flutter_driver.dart'; + +import 'package:integration_test/common.dart'; +import 'package:path/path.dart' as path; + +/// Flutter Driver test output directory. +/// +/// Tests should write any output files to this directory. Defaults to the path +/// set in the FLUTTER_TEST_OUTPUTS_DIR environment variable, or `build` if +/// unset. +String testOutputsDirectory = + Platform.environment['FLUTTER_TEST_OUTPUTS_DIR'] ?? 'build'; + +/// The callback type to handle [Response.data] after the test +/// succeeds. +typedef ResponseDataCallback = FutureOr Function(Map); + +/// Writes a json-serializable json data to to +/// [testOutputsDirectory]/`testOutputFilename.json`. +/// +/// This is the default `responseDataCallback` in [integrationDriver]. +Future writeResponseData( + Map data, { + String testOutputFilename = 'integration_response_data', + String destinationDirectory, +}) async { + assert(testOutputFilename != null); + destinationDirectory ??= testOutputsDirectory; + await fs.directory(destinationDirectory).create(recursive: true); + final File file = fs.file(path.join( + destinationDirectory, + '$testOutputFilename.json', + )); + final String resultString = _encodeJson(data, true); + await file.writeAsString(resultString); +} + +/// Adaptor to run an integration test using `flutter drive`. +/// +/// `timeout` controls the longest time waited before the test ends. +/// It is not necessarily the execution time for the test app: the test may +/// finish sooner than the `timeout`. +/// +/// `responseDataCallback` is the handler for processing [Response.data]. +/// The default value is `writeResponseData`. +/// +/// To an integration test `.dart` using `flutter drive`, put a file named +/// `_test.dart` in the app's `test_driver` directory: +/// +/// ```dart +/// import 'dart:async'; +/// +/// import 'package:integration_test/integration_test_driver.dart'; +/// +/// Future main() async => integrationDriver(); +/// +/// ``` +Future integrationDriver({ + Duration timeout = const Duration(minutes: 1), + ResponseDataCallback responseDataCallback = writeResponseData, +}) async { + final FlutterDriver driver = await FlutterDriver.connect(); + final String jsonResult = await driver.requestData(null, timeout: timeout); + final Response response = Response.fromJson(jsonResult); + await driver.close(); + + if (response.allTestsPassed) { + print('All tests passed.'); + if (responseDataCallback != null) { + await responseDataCallback(response.data); + } + exit(0); + } else { + print('Failure Details:\n${response.formattedFailureDetails}'); + exit(1); + } +} + +const JsonEncoder _prettyEncoder = JsonEncoder.withIndent(' '); + +String _encodeJson(Map jsonObject, bool pretty) { + return pretty ? _prettyEncoder.convert(jsonObject) : json.encode(jsonObject); +} diff --git a/packages/integration_test/lib/integration_test_driver_extended.dart b/packages/integration_test/lib/integration_test_driver_extended.dart new file mode 100644 index 0000000000..1622aca9f5 --- /dev/null +++ b/packages/integration_test/lib/integration_test_driver_extended.dart @@ -0,0 +1,74 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:async'; +import 'dart:io'; + +import 'package:flutter_driver/flutter_driver.dart'; + +import 'common.dart'; + +/// Example Integration Test which can also run WebDriver command depending on +/// the requests coming from the test methods. +Future integrationDriver( + {FlutterDriver driver, Function onScreenshot}) async { + driver ??= await FlutterDriver.connect(); + // Test states that it's waiting on web driver commands. + // [DriverTestMessage] is converted to string since json format causes an + // error if it's used as a message for requestData. + String jsonResponse = await driver.requestData(DriverTestMessage.pending().toString()); + + Response response = Response.fromJson(jsonResponse); + + // Until `integration_test` returns a [WebDriverCommandType.noop], keep + // executing WebDriver commands. + while (response.data != null && + response.data['web_driver_command'] != null && + response.data['web_driver_command'] != '${WebDriverCommandType.noop}') { + final String webDriverCommand = response.data['web_driver_command'] as String; + if (webDriverCommand == '${WebDriverCommandType.screenshot}') { + // Use `driver.screenshot()` method to get a screenshot of the web page. + final List screenshotImage = await driver.screenshot(); + final String screenshotName = response.data['screenshot_name'] as String; + + final bool screenshotSuccess = await onScreenshot(screenshotName, screenshotImage) as bool; + if (screenshotSuccess) { + jsonResponse = await driver.requestData(DriverTestMessage.complete().toString()); + } else { + jsonResponse = + await driver.requestData(DriverTestMessage.error().toString()); + } + + response = Response.fromJson(jsonResponse); + } else if (webDriverCommand == '${WebDriverCommandType.ack}') { + // Previous command completed ask for a new one. + jsonResponse = + await driver.requestData(DriverTestMessage.pending().toString()); + + response = Response.fromJson(jsonResponse); + } else { + break; + } + } + + // If No-op command is sent, ask for the result of all tests. + if (response.data != null && + response.data['web_driver_command'] != null && + response.data['web_driver_command'] == '${WebDriverCommandType.noop}') { + jsonResponse = await driver.requestData(null); + + response = Response.fromJson(jsonResponse); + print('result $jsonResponse'); + } + + await driver.close(); + + if (response.allTestsPassed) { + print('All tests passed.'); + exit(0); + } else { + print('Failure Details:\n${response.formattedFailureDetails}'); + exit(1); + } +} diff --git a/packages/integration_test/pubspec.yaml b/packages/integration_test/pubspec.yaml new file mode 100644 index 0000000000..130aaa5eb0 --- /dev/null +++ b/packages/integration_test/pubspec.yaml @@ -0,0 +1,58 @@ +name: integration_test +description: Runs tests that use the flutter_test API as integration tests. +version: 0.9.2+2 +publish_to: none +homepage: https://github.com/flutter/plugins/tree/master/packages/integration_test + +environment: + sdk: ">=2.10.0-0.0.dev <3.0.0" + +dependencies: + flutter: + sdk: flutter + flutter_driver: + sdk: flutter + flutter_test: + sdk: flutter + path: 1.8.0-nullsafety.3 + vm_service: 5.2.0 + + archive: 2.0.13 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + args: 1.6.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + async: 2.5.0-nullsafety.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + boolean_selector: 2.1.0-nullsafety.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + characters: 1.1.0-nullsafety.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + charcode: 1.2.0-nullsafety.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + clock: 1.1.0-nullsafety.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + collection: 1.15.0-nullsafety.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + convert: 2.1.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + crypto: 2.1.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + fake_async: 1.2.0-nullsafety.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + file: 6.0.0-nullsafety.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + matcher: 0.12.10-nullsafety.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + meta: 1.3.0-nullsafety.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + source_span: 1.8.0-nullsafety.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + stack_trace: 1.10.0-nullsafety.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + stream_channel: 2.1.0-nullsafety.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + string_scanner: 1.1.0-nullsafety.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + sync_http: 0.2.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + term_glyph: 1.2.0-nullsafety.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + test_api: 0.2.19-nullsafety.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + typed_data: 1.3.0-nullsafety.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + vector_math: 2.1.0-nullsafety.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + webdriver: 2.1.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + +dev_dependencies: + pedantic: 1.10.0-nullsafety.3 + mockito: 4.1.1 + +flutter: + plugin: + platforms: + android: + package: dev.flutter.plugins.integration_test + pluginClass: IntegrationTestPlugin + ios: + pluginClass: IntegrationTestPlugin + +# PUBSPEC CHECKSUM: f9bc diff --git a/packages/integration_test/test/binding_fail_test.dart b/packages/integration_test/test/binding_fail_test.dart new file mode 100644 index 0000000000..622c970c3b --- /dev/null +++ b/packages/integration_test/test/binding_fail_test.dart @@ -0,0 +1,79 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:async'; +import 'dart:convert'; +import 'dart:io'; + +import 'package:flutter_test/flutter_test.dart'; +import 'package:path/path.dart' as path; + +final String bat = Platform.isWindows ? '.bat' : ''; +final String _flutterBin = path.join(Directory.current.parent.parent.parent.path, 'bin', 'flutter$bat'); +const String _integrationResultsPrefix = + 'IntegrationTestWidgetsFlutterBinding test results:'; +const String _failureExcerpt = r'Expected: \n Actual: '; + +Future main() async { + group('Integration binding result', () { + test('when multiple tests pass', () async { + final Map results = await _runTest(path.join('test', 'data', 'pass_test_script.dart')); + + expect( + results, + equals({ + 'passing test 1': 'success', + 'passing test 2': 'success', + })); + }); + + test('when multiple tests fail', () async { + final Map results = await _runTest(path.join('test', 'data', 'fail_test_script.dart')); + + expect(results, hasLength(2)); + expect(results, containsPair('failing test 1', contains(_failureExcerpt))); + expect(results, containsPair('failing test 2', contains(_failureExcerpt))); + }); + + test('when one test passes, then another fails', () async { + final Map results = await _runTest(path.join('test', 'data', 'pass_then_fail_test_script.dart')); + + expect(results, hasLength(2)); + expect(results, containsPair('passing test', equals('success'))); + expect(results, containsPair('failing test', contains(_failureExcerpt))); + }); + }); +} + +/// Runs a test script and returns the [IntegrationTestWidgetsFlutterBinding.result]. +/// +/// [scriptPath] is relative to the package root. +Future> _runTest(String scriptPath) async { + final Process process = + await Process.start(_flutterBin, ['test', '--machine', scriptPath]); + + /// In the test [tearDownAll] block, the test results are encoded into JSON and + /// are printed with the [_integrationResultsPrefix] prefix. + /// + /// See the following for the test event spec which we parse the printed lines + /// out of: https://github.com/dart-lang/test/blob/master/pkgs/test/doc/json_reporter.md + final String testResults = (await process.stdout + .transform(utf8.decoder) + .expand((String text) => text.split('\n')) + .map((String line) { + try { + return jsonDecode(line) as Map; + } on FormatException { + // Only interested in test events which are JSON. + } + }) + .where((Map testEvent) => + testEvent != null && testEvent['type'] == 'print') + .map((Map printEvent) => printEvent['message'] as String) + .firstWhere((String message) => + message.startsWith(_integrationResultsPrefix))) + .replaceAll(_integrationResultsPrefix, ''); + + return jsonDecode(testResults) as Map; +} diff --git a/packages/integration_test/test/binding_test.dart b/packages/integration_test/test/binding_test.dart new file mode 100644 index 0000000000..03879a825a --- /dev/null +++ b/packages/integration_test/test/binding_test.dart @@ -0,0 +1,104 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:convert'; + +import 'package:flutter/material.dart'; + +import 'package:integration_test/integration_test.dart'; +import 'package:integration_test/common.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mockito/mockito.dart'; +import 'package:vm_service/vm_service.dart' as vm; + +vm.Timeline _kTimelines = vm.Timeline( + traceEvents: [], + timeOriginMicros: 100, + timeExtentMicros: 200, +); + +Future main() async { + Future> request; + + group('Test Integration binding', () { + final WidgetsBinding binding = IntegrationTestWidgetsFlutterBinding.ensureInitialized(); + assert(binding is IntegrationTestWidgetsFlutterBinding); + final IntegrationTestWidgetsFlutterBinding integrationBinding = binding as IntegrationTestWidgetsFlutterBinding; + + MockVM mockVM; + final List clockTimes = [100, 200]; + + setUp(() { + request = integrationBinding.callback({ + 'command': 'request_data', + }); + mockVM = MockVM(); + when(mockVM.getVMTimeline( + timeOriginMicros: anyNamed('timeOriginMicros'), + timeExtentMicros: anyNamed('timeExtentMicros'), + )).thenAnswer((_) => Future.value(_kTimelines)); + when(mockVM.getVMTimelineMicros()).thenAnswer( + (_) => Future.value(vm.Timestamp(timestamp: clockTimes.removeAt(0))), + ); + }); + + testWidgets('Run Integration app', (WidgetTester tester) async { + runApp(const MaterialApp( + home: Text('Test'), + )); + expect(tester.binding, integrationBinding); + integrationBinding.reportData = {'answer': 42}; + }); + + testWidgets('setSurfaceSize works', (WidgetTester tester) async { + await tester.pumpWidget(const MaterialApp(home: Center(child: Text('Test')))); + + final Size windowCenter = tester.binding.window.physicalSize / + tester.binding.window.devicePixelRatio / + 2; + final double windowCenterX = windowCenter.width; + final double windowCenterY = windowCenter.height; + + Offset widgetCenter = tester.getRect(find.byType(Text)).center; + expect(widgetCenter.dx, windowCenterX); + expect(widgetCenter.dy, windowCenterY); + + await tester.binding.setSurfaceSize(const Size(200, 300)); + await tester.pump(); + widgetCenter = tester.getRect(find.byType(Text)).center; + expect(widgetCenter.dx, 100); + expect(widgetCenter.dy, 150); + + await tester.binding.setSurfaceSize(null); + await tester.pump(); + widgetCenter = tester.getRect(find.byType(Text)).center; + expect(widgetCenter.dx, windowCenterX); + expect(widgetCenter.dy, windowCenterY); + }); + + testWidgets('Test traceAction', (WidgetTester tester) async { + await integrationBinding.enableTimeline(vmService: mockVM); + await integrationBinding.traceAction(() async {}); + expect(integrationBinding.reportData, isNotNull); + expect(integrationBinding.reportData.containsKey('timeline'), true); + expect( + json.encode(integrationBinding.reportData['timeline']), + json.encode(_kTimelines), + ); + }); + }); + + tearDownAll(() async { + // This part is outside the group so that `request` has been compeleted as + // part of the `tearDownAll` registerred in the group during + // `IntegrationTestWidgetsFlutterBinding` initialization. + final Map response = + (await request)['response'] as Map; + final String message = response['message'] as String; + final Response result = Response.fromJson(message); + assert(result.data['answer'] == 42); + }); +} + +class MockVM extends Mock implements vm.VmService {} diff --git a/packages/integration_test/test/data/README.md b/packages/integration_test/test/data/README.md new file mode 100644 index 0000000000..e52aca112c --- /dev/null +++ b/packages/integration_test/test/data/README.md @@ -0,0 +1,4 @@ +Files in this directory are not invoked directly by the test command. + +They are used as inputs for the other test files outside of this directory, so +that failures can be tested. \ No newline at end of file diff --git a/packages/integration_test/test/data/fail_test_script.dart b/packages/integration_test/test/data/fail_test_script.dart new file mode 100644 index 0000000000..58db5719dd --- /dev/null +++ b/packages/integration_test/test/data/fail_test_script.dart @@ -0,0 +1,24 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:convert'; + +import 'package:integration_test/integration_test.dart'; +import 'package:flutter_test/flutter_test.dart'; + +Future main() async { + final IntegrationTestWidgetsFlutterBinding binding = IntegrationTestWidgetsFlutterBinding.ensureInitialized() as IntegrationTestWidgetsFlutterBinding; + + testWidgets('failing test 1', (WidgetTester tester) async { + expect(true, false); + }); + + testWidgets('failing test 2', (WidgetTester tester) async { + expect(true, false); + }); + + tearDownAll(() { + print('IntegrationTestWidgetsFlutterBinding test results: ${jsonEncode(binding.results)}'); + }); +} diff --git a/packages/integration_test/test/data/pass_test_script.dart b/packages/integration_test/test/data/pass_test_script.dart new file mode 100644 index 0000000000..b0d3c95cac --- /dev/null +++ b/packages/integration_test/test/data/pass_test_script.dart @@ -0,0 +1,25 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:convert'; + +import 'package:integration_test/integration_test.dart'; +import 'package:flutter_test/flutter_test.dart'; + +Future main() async { + final IntegrationTestWidgetsFlutterBinding binding = IntegrationTestWidgetsFlutterBinding.ensureInitialized() as IntegrationTestWidgetsFlutterBinding; + + testWidgets('passing test 1', (WidgetTester tester) async { + expect(true, true); + }); + + testWidgets('passing test 2', (WidgetTester tester) async { + expect(true, true); + }); + + tearDownAll(() { + print( + 'IntegrationTestWidgetsFlutterBinding test results: ${jsonEncode(binding.results)}'); + }); +} diff --git a/packages/integration_test/test/data/pass_then_fail_test_script.dart b/packages/integration_test/test/data/pass_then_fail_test_script.dart new file mode 100644 index 0000000000..6597ac764c --- /dev/null +++ b/packages/integration_test/test/data/pass_then_fail_test_script.dart @@ -0,0 +1,25 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:convert'; + +import 'package:integration_test/integration_test.dart'; +import 'package:flutter_test/flutter_test.dart'; + +Future main() async { + final IntegrationTestWidgetsFlutterBinding binding = IntegrationTestWidgetsFlutterBinding.ensureInitialized() as IntegrationTestWidgetsFlutterBinding; + + testWidgets('passing test', (WidgetTester tester) async { + expect(true, true); + }); + + testWidgets('failing test', (WidgetTester tester) async { + expect(true, false); + }); + + tearDownAll(() { + print( + 'IntegrationTestWidgetsFlutterBinding test results: ${jsonEncode(binding.results)}'); + }); +} diff --git a/packages/integration_test/test/response_serialization_test.dart b/packages/integration_test/test/response_serialization_test.dart new file mode 100644 index 0000000000..dfcd5e88b9 --- /dev/null +++ b/packages/integration_test/test/response_serialization_test.dart @@ -0,0 +1,51 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:flutter_test/flutter_test.dart'; + +import 'package:integration_test/common.dart'; + +void main() { + test('Serialize and deserialize Failure', () { + final Failure fail = Failure('what a name', 'no detail'); + final Failure restored = Failure.fromJsonString(fail.toString()); + expect(restored.methodName, fail.methodName); + expect(restored.details, fail.details); + }); + + test('Serialize and deserialize Response', () { + Response response, restored; + String jsonString; + + response = Response.allTestsPassed(); + jsonString = response.toJson(); + expect(jsonString, '{"result":"true","failureDetails":[]}'); + restored = Response.fromJson(jsonString); + expect(restored.allTestsPassed, response.allTestsPassed); + expect(restored.data, null); + expect(restored.formattedFailureDetails, ''); + + final Failure fail = Failure('what a name', 'no detail'); + final Failure fail2 = Failure('what a name2', 'no detail2'); + response = Response.someTestsFailed([fail, fail2]); + jsonString = response.toJson(); + restored = Response.fromJson(jsonString); + expect(restored.allTestsPassed, response.allTestsPassed); + expect(restored.data, null); + expect(restored.formattedFailureDetails, response.formattedFailureDetails); + + final Map data = {'aaa': 'bbb'}; + response = Response.allTestsPassed(data: data); + jsonString = response.toJson(); + restored = Response.fromJson(jsonString); + expect(restored.data.keys, ['aaa']); + expect(restored.data.values, ['bbb']); + + response = Response.someTestsFailed([fail, fail2], data: data); + jsonString = response.toJson(); + restored = Response.fromJson(jsonString); + expect(restored.data.keys, ['aaa']); + expect(restored.data.values, ['bbb']); + }); +}