diff --git a/.github/workflows/pr_validation.yaml b/.github/workflows/pr_validation.yaml
new file mode 100644
index 0000000..93295ab
--- /dev/null
+++ b/.github/workflows/pr_validation.yaml
@@ -0,0 +1,251 @@
+name: Validate PR
+
+on: [pull_request, workflow_dispatch]
+
+jobs:
+# test_flutter-test-runners_deep-links_android:
+# runs-on: ubuntu-latest
+# defaults:
+# run:
+# working-directory: ./packages/flutter_test_runners/example_deep_links
+#
+# steps:
+# - name: Checkout Repository
+# uses: actions/checkout@v3
+#
+# # Need JDK 17 for Android build.
+# - name: Set up JDK 17
+# uses: actions/setup-java@v3
+# with:
+# distribution: 'temurin'
+# java-version: '17'
+#
+# # The Android emulator action seems to want to include this.
+# - name: enable KVM for linux runners
+# working-directory: ~
+# run: |
+# echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
+# sudo udevadm control --reload-rules
+# sudo udevadm trigger --name-match=kvm
+#
+# - name: Set up Flutter
+# uses: subosito/flutter-action@v2
+# with:
+# channel: stable
+# architecture: x64
+#
+# - name: Install Flutter Dependencies
+# run: flutter pub get
+#
+# - name: Build Flutter App (Debug Mode)
+# # Must be debug mode so we can enable Flutter Driver.
+# run: flutter build apk --debug
+#
+# - name: Install Android SDK and launch emulator
+# uses: reactivecircus/android-emulator-runner@v2
+# with:
+# api-level: 35
+# target: default
+# arch: x86_64
+# profile: Galaxy Nexus
+# cores: 2
+# disk-size: 6000M
+# heap-size: 600M
+# sdcard-path-or-size: 100M
+# avd-name: github-ci-emulator
+# force-avd-creation: false
+# emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
+# disable-animations: false
+# script: |
+# echo "Running emulator..."
+# echo "Working directory: $(pwd)"
+#
+# echo "Unlocking the screen"
+# adb shell input keyevent 82 # Unlock the emulator screen if it's locked
+# echo ""
+#
+# echo "Installing the APK"
+# cd packages/flutter_test_runners/example_deep_links && flutter install --debug -d emulator-5554
+# echo ""
+#
+# echo "Running Flutter tests"
+# cd packages/flutter_test_runners/example_deep_links && flutter test test_driver/deep_link_android_test.dart
+
+ test_flutter-test-runners_deep-links_ios:
+ runs-on: macos-latest
+
+ defaults:
+ run:
+ working-directory: ./packages/flutter_test_runners/example_deep_links
+
+ steps:
+ - name: Set location for ExportOptions.plist
+ working-directory: ~
+ run: |
+ echo "EXPORT_OPTS_PATH=$RUNNER_TEMP/ExportOptions.plist" >> $GITHUB_ENV
+
+ - name: Install the Apple certificate and provisioning profile
+ working-directory: ~
+ env:
+ BUILD_CERTIFICATE_BASE64: ${{ secrets.SIGNING_CERTIFICATE }}
+ P12_PASSWORD: ${{ secrets.SIGNING_CERTIFICATE_PASSWORD }}
+ BUILD_PROVISION_PROFILE_BASE64: ${{ secrets.PROVISIONING_PROFILE }}
+ PP_FILE_NAME: fbh_deep_link_example_app_profile.mobileprovision
+ EXPORT_OPTIONS_PLIST: ${{ secrets.EXPORT_OPTIONS_PLIST }}
+ run: |
+ # Create variables
+ CERTIFICATE_PATH=$RUNNER_TEMP/build_certificate.p12
+ PP_PATH=$RUNNER_TEMP/$PP_FILE_NAME
+ KEYCHAIN_PATH=~/Library/Keychains/login.keychain-db
+
+ # Check keychain status
+ echo "All keychains:"
+ security list-keychains
+
+ echo "Is keychain unlocked?"
+ security show-keychain-info $KEYCHAIN_PATH
+
+ # Import certificate and provisioning profile from secrets
+ echo -n "$BUILD_CERTIFICATE_BASE64" | base64 --decode -o $CERTIFICATE_PATH
+ echo -n "$BUILD_PROVISION_PROFILE_BASE64" | base64 --decode -o $PP_PATH
+
+ # create temporary keychain
+ #security create-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
+ #security set-keychain-settings -lut 21600 $KEYCHAIN_PATH
+ #security unlock-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
+
+ # Import certificate to keychain
+ security import $CERTIFICATE_PATH -P "$P12_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH
+ security list-keychain -d user -s $KEYCHAIN_PATH
+
+ # Verify certificate was loaded into keychain
+ echo "Verifying that the signing certificate was loaded into the keychain"
+ security find-identity -p codesigning -v
+
+ # Apply provisioning profile
+ mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles
+ cp $PP_PATH ~/Library/MobileDevice/Provisioning\ Profiles
+
+ # List all provisioning profiles to make sure we placed it correctly
+ echo "Listing all provisioning profiles in the CI server"
+ ls ~/Library/MobileDevice/Provisioning\ Profiles/
+ echo ""
+
+ # Check provisioning profile data
+ echo "Provisioning profile data:"
+ security cms -D -i ~/Library/MobileDevice/Provisioning\ Profiles/$PP_FILE_NAME
+ echo ""
+
+ # Save ExportOptions.plist from Base64 to file
+ echo "Saving the base64 encoded ExportOptions.plist to $EXPORT_OPTS_PATH"
+ echo -n "$EXPORT_OPTIONS_PLIST" | base64 --decode -o $EXPORT_OPTS_PATH
+
+ - name: Checkout repository
+ uses: actions/checkout@v3
+
+ - name: Set up Xcode
+ run: |
+ sudo xcode-select -s /Applications/Xcode.app
+ xcodebuild -version
+
+ - name: Check Xcode build settings
+ run: |
+ echo "Listing all the build settings for the project:"
+ cd ios && xcodebuild -showBuildSettings
+
+ - name: Check Xcode project Runner build settings
+ run: |
+ echo "Listing all the build settings for the Runner scheme:"
+ cd ios && xcodebuild -workspace Runner.xcworkspace -scheme Runner -showBuildSettings
+
+ - name: Set up Flutter
+ uses: subosito/flutter-action@v2
+ with:
+ channel: stable
+ architecture: x64
+
+ - name: Install Flutter Dependencies
+ run: flutter pub get
+
+ - name: Build the app
+ run: flutter build ios --debug --verbose --simulator --no-codesign
+
+ - name: Check for built app
+ run: |
+ echo "Checking for app build artifacts..."
+ echo "build/"
+ ls -la build
+ echo ""
+
+ echo "build/ios/"
+ ls -la build/ios
+ echo ""
+
+ echo "build/ios/Debug-iphonesimulator/"
+ ls -la build/ios/Debug-iphonesimulator
+ echo ""
+
+ echo "build/ios/iphonesimulator/"
+ ls -la build/ios/iphonesimulator
+ echo ""
+
+# - name: Build iOS App
+# run: flutter build ipa --debug --verbose --export-options-plist=$EXPORT_OPTS_PATH
+#
+# - name: Install iOS App
+# run: flutter install ipa
+
+ - name: Create and Boot iOS Simulator
+ run: |
+ # List available devices and runtimes
+ xcrun simctl list devices
+ xcrun simctl list runtimes
+
+ # Create a new simulator (if needed)
+ SIMULATOR_ID=$(xcrun simctl create "GitHubActions-Simulator" "iPhone 14" "com.apple.CoreSimulator.SimRuntime.iOS-17-0")
+
+ # Boot the simulator
+ xcrun simctl boot "$SIMULATOR_ID"
+ xcrun simctl list devices booted
+
+ # Install the app using xcrun. Apparently, there's no Flutter command to
+ # install an unsigned iOS app. The "flutter install" command only works if
+ # the app is signed.
+ - name: Install the app
+ run: xcrun simctl install booted build/ios/iphonesimulator/Runner.app
+
+ - name: Ensure simulator is booted
+ run: xcrun simctl bootstatus booted
+
+ - name: Check the simulator UI
+ run: xcrun simctl ui booted appearance
+
+ - name: Take a screenshot of the simulator
+ run: |
+ mkdir -p ~/simulator-screenshots
+ xcrun simctl io booted screenshot ~/simulator-screenshots/screenshot.png
+
+ - name: Upload simulator screenshot as Artifact
+ uses: actions/upload-artifact@v3
+ with:
+ name: simulator-screenshot
+ path: ~/simulator-screenshots/screenshot.png
+
+ - name: Check for installed app on simulator
+ run: |
+ echo "Checking for app's container on the booted simulator:"
+ xcrun simctl get_app_container booted com.flutterbountyhunters.deeplinks.example
+
+# - name: Kill any simctl processes
+# run: pkill -f runner
+#
+# - name: Check for other processes using the simulator
+# run: ps aux | grep simctl
+
+ # - name: Launch the app on the simulator just to prove we can
+# run: |
+# echo "Launching the installed app to prove that we can..."
+# xcrun simctl launch booted com.flutterbountyhunters.deeplinks.example
+
+ - name: Run the iOS deep link tests
+ run: flutter test test_driver/deep_link_ios_test.dart
diff --git a/.run/Example_ Deep Links.run.xml b/.run/Example_ Deep Links.run.xml
new file mode 100644
index 0000000..fe7fa30
--- /dev/null
+++ b/.run/Example_ Deep Links.run.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/melos_flutter_testing.iml b/melos_flutter_testing.iml
index 9681559..01e7ecf 100644
--- a/melos_flutter_testing.iml
+++ b/melos_flutter_testing.iml
@@ -4,9 +4,12 @@
+
+
+
-
+
\ No newline at end of file
diff --git a/packages/flutter_test_runners/example_deep_links/.gitignore b/packages/flutter_test_runners/example_deep_links/.gitignore
new file mode 100644
index 0000000..79c113f
--- /dev/null
+++ b/packages/flutter_test_runners/example_deep_links/.gitignore
@@ -0,0 +1,45 @@
+# Miscellaneous
+*.class
+*.log
+*.pyc
+*.swp
+.DS_Store
+.atom/
+.build/
+.buildlog/
+.history
+.svn/
+.swiftpm/
+migrate_working_dir/
+
+# 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/
+**/ios/Flutter/.last_build_id
+.dart_tool/
+.flutter-plugins
+.flutter-plugins-dependencies
+.pub-cache/
+.pub/
+/build/
+
+# Symbolication related
+app.*.symbols
+
+# Obfuscation related
+app.*.map.json
+
+# Android Studio will place build artifacts here
+/android/app/debug
+/android/app/profile
+/android/app/release
diff --git a/packages/flutter_test_runners/example_deep_links/.metadata b/packages/flutter_test_runners/example_deep_links/.metadata
new file mode 100644
index 0000000..556b647
--- /dev/null
+++ b/packages/flutter_test_runners/example_deep_links/.metadata
@@ -0,0 +1,33 @@
+# This file tracks properties of this Flutter project.
+# Used by Flutter tool to assess capabilities and perform upgrades etc.
+#
+# This file should be version controlled and should not be manually edited.
+
+version:
+ revision: "17025dd88227cd9532c33fa78f5250d548d87e9a"
+ channel: "stable"
+
+project_type: app
+
+# Tracks metadata for the flutter migrate command
+migration:
+ platforms:
+ - platform: root
+ create_revision: 17025dd88227cd9532c33fa78f5250d548d87e9a
+ base_revision: 17025dd88227cd9532c33fa78f5250d548d87e9a
+ - platform: android
+ create_revision: 17025dd88227cd9532c33fa78f5250d548d87e9a
+ base_revision: 17025dd88227cd9532c33fa78f5250d548d87e9a
+ - platform: ios
+ create_revision: 17025dd88227cd9532c33fa78f5250d548d87e9a
+ base_revision: 17025dd88227cd9532c33fa78f5250d548d87e9a
+
+ # User provided section
+
+ # List of Local paths (relative to this file) that should be
+ # ignored by the migrate tool.
+ #
+ # Files that are not part of the templates will be ignored by default.
+ unmanaged_files:
+ - 'lib/main.dart'
+ - 'ios/Runner.xcodeproj/project.pbxproj'
diff --git a/packages/flutter_test_runners/example_deep_links/README.md b/packages/flutter_test_runners/example_deep_links/README.md
new file mode 100644
index 0000000..3b05925
--- /dev/null
+++ b/packages/flutter_test_runners/example_deep_links/README.md
@@ -0,0 +1,3 @@
+# Example: Deep Links
+This app is configured for deep links so that `flutter_test_runner` deep link
+verification tools can be validated.
diff --git a/packages/flutter_test_runners/example_deep_links/analysis_options.yaml b/packages/flutter_test_runners/example_deep_links/analysis_options.yaml
new file mode 100644
index 0000000..0d29021
--- /dev/null
+++ b/packages/flutter_test_runners/example_deep_links/analysis_options.yaml
@@ -0,0 +1,28 @@
+# This file configures the analyzer, which statically analyzes Dart code to
+# check for errors, warnings, and lints.
+#
+# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
+# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
+# invoked from the command line by running `flutter analyze`.
+
+# The following line activates a set of recommended lints for Flutter apps,
+# packages, and plugins designed to encourage good coding practices.
+include: package:flutter_lints/flutter.yaml
+
+linter:
+ # The lint rules applied to this project can be customized in the
+ # section below to disable rules from the `package:flutter_lints/flutter.yaml`
+ # included above or to enable additional rules. A list of all available lints
+ # and their documentation is published at https://dart.dev/lints.
+ #
+ # Instead of disabling a lint rule for the entire project in the
+ # section below, it can also be suppressed for a single line of code
+ # or a specific dart file by using the `// ignore: name_of_lint` and
+ # `// ignore_for_file: name_of_lint` syntax on the line or in the file
+ # producing the lint.
+ rules:
+ # avoid_print: false # Uncomment to disable the `avoid_print` rule
+ # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
+
+# Additional information about this file can be found at
+# https://dart.dev/guides/language/analysis-options
diff --git a/packages/flutter_test_runners/example_deep_links/android/.gitignore b/packages/flutter_test_runners/example_deep_links/android/.gitignore
new file mode 100644
index 0000000..55afd91
--- /dev/null
+++ b/packages/flutter_test_runners/example_deep_links/android/.gitignore
@@ -0,0 +1,13 @@
+gradle-wrapper.jar
+/.gradle
+/captures/
+/gradlew
+/gradlew.bat
+/local.properties
+GeneratedPluginRegistrant.java
+
+# Remember to never publicly share your keystore.
+# See https://flutter.dev/to/reference-keystore
+key.properties
+**/*.keystore
+**/*.jks
diff --git a/packages/flutter_test_runners/example_deep_links/android/app/build.gradle b/packages/flutter_test_runners/example_deep_links/android/app/build.gradle
new file mode 100644
index 0000000..d38b7ef
--- /dev/null
+++ b/packages/flutter_test_runners/example_deep_links/android/app/build.gradle
@@ -0,0 +1,43 @@
+plugins {
+ id "com.android.application"
+ id "kotlin-android"
+ // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
+ id "dev.flutter.flutter-gradle-plugin"
+}
+
+android {
+ namespace = "com.flutterbountyhunters.deeplinks.example"
+ compileSdk = flutter.compileSdkVersion
+ ndkVersion = flutter.ndkVersion
+
+ compileOptions {
+ sourceCompatibility = JavaVersion.VERSION_1_8
+ targetCompatibility = JavaVersion.VERSION_1_8
+ }
+
+ kotlinOptions {
+ jvmTarget = JavaVersion.VERSION_1_8
+ }
+
+ defaultConfig {
+ applicationId = "com.flutterbountyhunters.deeplinks.example"
+ // You can update the following values to match your application needs.
+ // For more information, see: https://flutter.dev/to/review-gradle-config.
+ minSdk = flutter.minSdkVersion
+ targetSdk = flutter.targetSdkVersion
+ versionCode = flutter.versionCode
+ versionName = flutter.versionName
+ }
+
+ 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 = "../.."
+}
diff --git a/packages/flutter_test_runners/example_deep_links/android/app/src/debug/AndroidManifest.xml b/packages/flutter_test_runners/example_deep_links/android/app/src/debug/AndroidManifest.xml
new file mode 100644
index 0000000..399f698
--- /dev/null
+++ b/packages/flutter_test_runners/example_deep_links/android/app/src/debug/AndroidManifest.xml
@@ -0,0 +1,7 @@
+
+
+
+
diff --git a/packages/flutter_test_runners/example_deep_links/android/app/src/main/AndroidManifest.xml b/packages/flutter_test_runners/example_deep_links/android/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..f21c4cd
--- /dev/null
+++ b/packages/flutter_test_runners/example_deep_links/android/app/src/main/AndroidManifest.xml
@@ -0,0 +1,58 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/flutter_test_runners/example_deep_links/android/app/src/main/kotlin/com/flutterbountyhunters/deeplinks/example/MainActivity.kt b/packages/flutter_test_runners/example_deep_links/android/app/src/main/kotlin/com/flutterbountyhunters/deeplinks/example/MainActivity.kt
new file mode 100644
index 0000000..1cdafcc
--- /dev/null
+++ b/packages/flutter_test_runners/example_deep_links/android/app/src/main/kotlin/com/flutterbountyhunters/deeplinks/example/MainActivity.kt
@@ -0,0 +1,5 @@
+package com.flutterbountyhunters.deeplinks.example;
+
+import io.flutter.embedding.android.FlutterActivity
+
+class MainActivity: FlutterActivity()
diff --git a/packages/flutter_test_runners/example_deep_links/android/app/src/main/res/drawable-v21/launch_background.xml b/packages/flutter_test_runners/example_deep_links/android/app/src/main/res/drawable-v21/launch_background.xml
new file mode 100644
index 0000000..f74085f
--- /dev/null
+++ b/packages/flutter_test_runners/example_deep_links/android/app/src/main/res/drawable-v21/launch_background.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
diff --git a/packages/flutter_test_runners/example_deep_links/android/app/src/main/res/drawable/launch_background.xml b/packages/flutter_test_runners/example_deep_links/android/app/src/main/res/drawable/launch_background.xml
new file mode 100644
index 0000000..304732f
--- /dev/null
+++ b/packages/flutter_test_runners/example_deep_links/android/app/src/main/res/drawable/launch_background.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
diff --git a/packages/flutter_test_runners/example_deep_links/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/packages/flutter_test_runners/example_deep_links/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..db77bb4
Binary files /dev/null and b/packages/flutter_test_runners/example_deep_links/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/packages/flutter_test_runners/example_deep_links/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/packages/flutter_test_runners/example_deep_links/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..17987b7
Binary files /dev/null and b/packages/flutter_test_runners/example_deep_links/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/packages/flutter_test_runners/example_deep_links/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/packages/flutter_test_runners/example_deep_links/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..09d4391
Binary files /dev/null and b/packages/flutter_test_runners/example_deep_links/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/packages/flutter_test_runners/example_deep_links/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/packages/flutter_test_runners/example_deep_links/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..d5f1c8d
Binary files /dev/null and b/packages/flutter_test_runners/example_deep_links/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/packages/flutter_test_runners/example_deep_links/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/packages/flutter_test_runners/example_deep_links/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..4d6372e
Binary files /dev/null and b/packages/flutter_test_runners/example_deep_links/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/packages/flutter_test_runners/example_deep_links/android/app/src/main/res/values-night/styles.xml b/packages/flutter_test_runners/example_deep_links/android/app/src/main/res/values-night/styles.xml
new file mode 100644
index 0000000..06952be
--- /dev/null
+++ b/packages/flutter_test_runners/example_deep_links/android/app/src/main/res/values-night/styles.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
diff --git a/packages/flutter_test_runners/example_deep_links/android/app/src/main/res/values/styles.xml b/packages/flutter_test_runners/example_deep_links/android/app/src/main/res/values/styles.xml
new file mode 100644
index 0000000..cb1ef88
--- /dev/null
+++ b/packages/flutter_test_runners/example_deep_links/android/app/src/main/res/values/styles.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
diff --git a/packages/flutter_test_runners/example_deep_links/android/app/src/profile/AndroidManifest.xml b/packages/flutter_test_runners/example_deep_links/android/app/src/profile/AndroidManifest.xml
new file mode 100644
index 0000000..399f698
--- /dev/null
+++ b/packages/flutter_test_runners/example_deep_links/android/app/src/profile/AndroidManifest.xml
@@ -0,0 +1,7 @@
+
+
+
+
diff --git a/packages/flutter_test_runners/example_deep_links/android/build.gradle b/packages/flutter_test_runners/example_deep_links/android/build.gradle
new file mode 100644
index 0000000..d2ffbff
--- /dev/null
+++ b/packages/flutter_test_runners/example_deep_links/android/build.gradle
@@ -0,0 +1,18 @@
+allprojects {
+ repositories {
+ google()
+ mavenCentral()
+ }
+}
+
+rootProject.buildDir = "../build"
+subprojects {
+ project.buildDir = "${rootProject.buildDir}/${project.name}"
+}
+subprojects {
+ project.evaluationDependsOn(":app")
+}
+
+tasks.register("clean", Delete) {
+ delete rootProject.buildDir
+}
diff --git a/packages/flutter_test_runners/example_deep_links/android/gradle.properties b/packages/flutter_test_runners/example_deep_links/android/gradle.properties
new file mode 100644
index 0000000..2597170
--- /dev/null
+++ b/packages/flutter_test_runners/example_deep_links/android/gradle.properties
@@ -0,0 +1,3 @@
+org.gradle.jvmargs=-Xmx4G -XX:MaxMetaspaceSize=2G -XX:+HeapDumpOnOutOfMemoryError
+android.useAndroidX=true
+android.enableJetifier=true
diff --git a/packages/flutter_test_runners/example_deep_links/android/gradle/wrapper/gradle-wrapper.properties b/packages/flutter_test_runners/example_deep_links/android/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..7bb2df6
--- /dev/null
+++ b/packages/flutter_test_runners/example_deep_links/android/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,5 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-all.zip
diff --git a/packages/flutter_test_runners/example_deep_links/android/settings.gradle b/packages/flutter_test_runners/example_deep_links/android/settings.gradle
new file mode 100644
index 0000000..b9e43bd
--- /dev/null
+++ b/packages/flutter_test_runners/example_deep_links/android/settings.gradle
@@ -0,0 +1,25 @@
+pluginManagement {
+ def flutterSdkPath = {
+ def properties = new Properties()
+ file("local.properties").withInputStream { properties.load(it) }
+ def flutterSdkPath = properties.getProperty("flutter.sdk")
+ assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
+ return flutterSdkPath
+ }()
+
+ includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
+
+ repositories {
+ google()
+ mavenCentral()
+ gradlePluginPortal()
+ }
+}
+
+plugins {
+ id "dev.flutter.flutter-plugin-loader" version "1.0.0"
+ id "com.android.application" version "8.1.0" apply false
+ id "org.jetbrains.kotlin.android" version "1.8.22" apply false
+}
+
+include ":app"
diff --git a/packages/flutter_test_runners/example_deep_links/apple_deep_links_hosting/.firebaserc b/packages/flutter_test_runners/example_deep_links/apple_deep_links_hosting/.firebaserc
new file mode 100644
index 0000000..6b945cd
--- /dev/null
+++ b/packages/flutter_test_runners/example_deep_links/apple_deep_links_hosting/.firebaserc
@@ -0,0 +1,15 @@
+{
+ "projects": {
+ "default": "flutter-bounty-hunters"
+ },
+ "targets": {
+ "flutter-bounty-hunters": {
+ "hosting": {
+ "deeplinks-flutter-bounty-hunters": [
+ "deeplinks-flutter-bounty-hunters"
+ ]
+ }
+ }
+ },
+ "etags": {}
+}
\ No newline at end of file
diff --git a/packages/flutter_test_runners/example_deep_links/apple_deep_links_hosting/.gitignore b/packages/flutter_test_runners/example_deep_links/apple_deep_links_hosting/.gitignore
new file mode 100644
index 0000000..b17f631
--- /dev/null
+++ b/packages/flutter_test_runners/example_deep_links/apple_deep_links_hosting/.gitignore
@@ -0,0 +1,69 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+firebase-debug.log*
+firebase-debug.*.log*
+
+# Firebase cache
+.firebase/
+
+# Firebase config
+
+# Uncomment this if you'd like others to create their own Firebase project.
+# For a team working on the same Firebase project(s), it is recommended to leave
+# it commented so all members can deploy to the same project(s) in .firebaserc.
+# .firebaserc
+
+# Runtime data
+pids
+*.pid
+*.seed
+*.pid.lock
+
+# Directory for instrumented libs generated by jscoverage/JSCover
+lib-cov
+
+# Coverage directory used by tools like istanbul
+coverage
+
+# nyc test coverage
+.nyc_output
+
+# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
+.grunt
+
+# Bower dependency directory (https://bower.io/)
+bower_components
+
+# node-waf configuration
+.lock-wscript
+
+# Compiled binary addons (http://nodejs.org/api/addons.html)
+build/Release
+
+# Dependency directories
+node_modules/
+
+# Optional npm cache directory
+.npm
+
+# Optional eslint cache
+.eslintcache
+
+# Optional REPL history
+.node_repl_history
+
+# Output of 'npm pack'
+*.tgz
+
+# Yarn Integrity file
+.yarn-integrity
+
+# dotenv environment variables file
+.env
+
+# dataconnect generated files
+.dataconnect
diff --git a/packages/flutter_test_runners/example_deep_links/apple_deep_links_hosting/README.md b/packages/flutter_test_runners/example_deep_links/apple_deep_links_hosting/README.md
new file mode 100644
index 0000000..da49598
--- /dev/null
+++ b/packages/flutter_test_runners/example_deep_links/apple_deep_links_hosting/README.md
@@ -0,0 +1,23 @@
+# Apple Deep Link Hosting Website
+This directory holds a website with the explicit purpose of hosting a
+`apple-app-site-association` file, as required by Apple, to associate
+an app with a Universal Link.
+
+This website defines an association for `deeplinks.flutterbountyhunters.com`,
+which is used only by `example_deep_links` in this repository. This
+association makes it possible for the FBH team to run the iOS deep link
+tests locally, and (maybe) run them in CI.
+
+If you're not a member of the FBH team, you won't be able to run the deep
+links in this example project, as-is. That's because you can't sign the app,
+because you're not a member of our Apple developer organization. If you
+want to run the iOS deep link code in this repository, you should do the following:
+
+ 1. Change the example app iOS app bundle ID to one that you own, e.g., `com.mydomain.myapp`.
+ 2. Change the Universal Links in this repo to point to a domain you own, e.g., `https://myapp.mydomain.com`.
+ 3. (If not done already) Upload an `apple-app-site-association` file to the domain you own.
+
+### Hosting
+This website is hosted on Firebase. This was chosen only because it was trivial
+to setup, and the configuration can be saved in this directory. It doesn't generally
+matter how the hosting is accomplished.
diff --git a/packages/flutter_test_runners/example_deep_links/apple_deep_links_hosting/firebase.json b/packages/flutter_test_runners/example_deep_links/apple_deep_links_hosting/firebase.json
new file mode 100644
index 0000000..4497ded
--- /dev/null
+++ b/packages/flutter_test_runners/example_deep_links/apple_deep_links_hosting/firebase.json
@@ -0,0 +1,22 @@
+{
+ "hosting": {
+ "target": "deeplinks-flutter-bounty-hunters",
+ "public": "public",
+ "headers": [
+ {
+ "source": ".well-known/apple-app-site-association",
+ "headers": [
+ {
+ "key": "Content-Type",
+ "value": "application/json"
+ }
+ ]
+ }
+ ],
+ "ignore": [
+ "firebase.json",
+ "**/.*",
+ "**/node_modules/**"
+ ]
+ }
+}
diff --git a/packages/flutter_test_runners/example_deep_links/apple_deep_links_hosting/public/.well-known/apple-app-site-association b/packages/flutter_test_runners/example_deep_links/apple_deep_links_hosting/public/.well-known/apple-app-site-association
new file mode 100644
index 0000000..5ce8221
--- /dev/null
+++ b/packages/flutter_test_runners/example_deep_links/apple_deep_links_hosting/public/.well-known/apple-app-site-association
@@ -0,0 +1,25 @@
+{
+ "applinks": {
+ "apps": [],
+ "details": [
+ {
+ "appIDs": [
+ "2X9AB296W2.com.flutterbountyhunters.deeplinks.example"
+ ],
+ "paths": [
+ "*"
+ ],
+ "components": [
+ {
+ "/": "/*"
+ }
+ ]
+ }
+ ]
+ },
+ "webcredentials": {
+ "apps": [
+ "2X9AB296W2.com.flutterbountyhunters.deeplinks.example"
+ ]
+ }
+}
\ No newline at end of file
diff --git a/packages/flutter_test_runners/example_deep_links/ios/.gitignore b/packages/flutter_test_runners/example_deep_links/ios/.gitignore
new file mode 100644
index 0000000..7a7f987
--- /dev/null
+++ b/packages/flutter_test_runners/example_deep_links/ios/.gitignore
@@ -0,0 +1,34 @@
+**/dgph
+*.mode1v3
+*.mode2v3
+*.moved-aside
+*.pbxuser
+*.perspectivev3
+**/*sync/
+.sconsign.dblite
+.tags*
+**/.vagrant/
+**/DerivedData/
+Icon?
+**/Pods/
+**/.symlinks/
+profile
+xcuserdata
+**/.generated/
+Flutter/App.framework
+Flutter/Flutter.framework
+Flutter/Flutter.podspec
+Flutter/Generated.xcconfig
+Flutter/ephemeral/
+Flutter/app.flx
+Flutter/app.zip
+Flutter/flutter_assets/
+Flutter/flutter_export_environment.sh
+ServiceDefinitions.json
+Runner/GeneratedPluginRegistrant.*
+
+# Exceptions to above rules.
+!default.mode1v3
+!default.mode2v3
+!default.pbxuser
+!default.perspectivev3
diff --git a/packages/flutter_test_runners/example_deep_links/ios/Flutter/AppFrameworkInfo.plist b/packages/flutter_test_runners/example_deep_links/ios/Flutter/AppFrameworkInfo.plist
new file mode 100644
index 0000000..7c56964
--- /dev/null
+++ b/packages/flutter_test_runners/example_deep_links/ios/Flutter/AppFrameworkInfo.plist
@@ -0,0 +1,26 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ en
+ CFBundleExecutable
+ App
+ CFBundleIdentifier
+ io.flutter.flutter.app
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ App
+ CFBundlePackageType
+ FMWK
+ CFBundleShortVersionString
+ 1.0
+ CFBundleSignature
+ ????
+ CFBundleVersion
+ 1.0
+ MinimumOSVersion
+ 12.0
+
+
diff --git a/packages/flutter_test_runners/example_deep_links/ios/Flutter/Debug.xcconfig b/packages/flutter_test_runners/example_deep_links/ios/Flutter/Debug.xcconfig
new file mode 100644
index 0000000..592ceee
--- /dev/null
+++ b/packages/flutter_test_runners/example_deep_links/ios/Flutter/Debug.xcconfig
@@ -0,0 +1 @@
+#include "Generated.xcconfig"
diff --git a/packages/flutter_test_runners/example_deep_links/ios/Flutter/Release.xcconfig b/packages/flutter_test_runners/example_deep_links/ios/Flutter/Release.xcconfig
new file mode 100644
index 0000000..592ceee
--- /dev/null
+++ b/packages/flutter_test_runners/example_deep_links/ios/Flutter/Release.xcconfig
@@ -0,0 +1 @@
+#include "Generated.xcconfig"
diff --git a/packages/flutter_test_runners/example_deep_links/ios/Runner.xcodeproj/project.pbxproj b/packages/flutter_test_runners/example_deep_links/ios/Runner.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..ceed118
--- /dev/null
+++ b/packages/flutter_test_runners/example_deep_links/ios/Runner.xcodeproj/project.pbxproj
@@ -0,0 +1,633 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 54;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
+ 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; };
+ 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
+ 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
+ 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 */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXContainerItemProxy section */
+ 331C8085294A63A400263BE5 /* 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 = (
+ );
+ name = "Embed Frameworks";
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXCopyFilesBuildPhase section */
+
+/* Begin PBXFileReference section */
+ 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 = ""; };
+ 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; };
+ 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
+ 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; };
+ 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; };
+ 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
+ 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; };
+ 84F387BE2D1FE87400CD6E2C /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; 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 = ""; };
+ 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ 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 = ""; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 97C146EB1CF9000F007C117D /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 331C8082294A63A400263BE5 /* RunnerTests */ = {
+ isa = PBXGroup;
+ children = (
+ 331C807B294A618700263BE5 /* RunnerTests.swift */,
+ );
+ path = RunnerTests;
+ sourceTree = "";
+ };
+ 9740EEB11CF90186004384FC /* Flutter */ = {
+ isa = PBXGroup;
+ children = (
+ 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
+ 9740EEB21CF90195004384FC /* Debug.xcconfig */,
+ 7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
+ 9740EEB31CF90195004384FC /* Generated.xcconfig */,
+ );
+ name = Flutter;
+ sourceTree = "";
+ };
+ 97C146E51CF9000F007C117D = {
+ isa = PBXGroup;
+ children = (
+ 9740EEB11CF90186004384FC /* Flutter */,
+ 97C146F01CF9000F007C117D /* Runner */,
+ 97C146EF1CF9000F007C117D /* Products */,
+ 331C8082294A63A400263BE5 /* RunnerTests */,
+ );
+ sourceTree = "";
+ };
+ 97C146EF1CF9000F007C117D /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 97C146EE1CF9000F007C117D /* Runner.app */,
+ 331C8081294A63A400263BE5 /* RunnerTests.xctest */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
+ 97C146F01CF9000F007C117D /* Runner */ = {
+ isa = PBXGroup;
+ children = (
+ 84F387BE2D1FE87400CD6E2C /* Runner.entitlements */,
+ 97C146FA1CF9000F007C117D /* Main.storyboard */,
+ 97C146FD1CF9000F007C117D /* Assets.xcassets */,
+ 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
+ 97C147021CF9000F007C117D /* Info.plist */,
+ 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
+ 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
+ 74858FAE1ED2DC5600515810 /* AppDelegate.swift */,
+ 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */,
+ );
+ path = Runner;
+ sourceTree = "";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ 331C8080294A63A400263BE5 /* RunnerTests */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */;
+ buildPhases = (
+ 331C807D294A63A400263BE5 /* Sources */,
+ 331C807F294A63A400263BE5 /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ 331C8086294A63A400263BE5 /* PBXTargetDependency */,
+ );
+ name = RunnerTests;
+ productName = RunnerTests;
+ productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */;
+ productType = "com.apple.product-type.bundle.unit-test";
+ };
+ 97C146ED1CF9000F007C117D /* Runner */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
+ buildPhases = (
+ 9740EEB61CF901F6004384FC /* Run Script */,
+ 97C146EA1CF9000F007C117D /* Sources */,
+ 97C146EB1CF9000F007C117D /* Frameworks */,
+ 97C146EC1CF9000F007C117D /* Resources */,
+ 9705A1C41CF9048500538489 /* Embed Frameworks */,
+ 3B06AD1E1E4923F5004D2608 /* Thin Binary */,
+ );
+ 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 = {
+ BuildIndependentTargetsInParallel = YES;
+ LastUpgradeCheck = 1510;
+ ORGANIZATIONNAME = "";
+ TargetAttributes = {
+ 331C8080294A63A400263BE5 = {
+ CreatedOnToolsVersion = 14.0;
+ TestTargetID = 97C146ED1CF9000F007C117D;
+ };
+ 97C146ED1CF9000F007C117D = {
+ CreatedOnToolsVersion = 7.3.1;
+ LastSwiftMigration = 1100;
+ };
+ };
+ };
+ buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
+ compatibilityVersion = "Xcode 9.3";
+ developmentRegion = en;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ Base,
+ );
+ mainGroup = 97C146E51CF9000F007C117D;
+ productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 97C146ED1CF9000F007C117D /* Runner */,
+ 331C8080294A63A400263BE5 /* RunnerTests */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+ 331C807F294A63A400263BE5 /* 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 */
+ 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
+ isa = PBXShellScriptBuildPhase;
+ alwaysOutOfDate = 1;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}",
+ );
+ name = "Thin Binary";
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
+ };
+ 9740EEB61CF901F6004384FC /* Run Script */ = {
+ isa = PBXShellScriptBuildPhase;
+ alwaysOutOfDate = 1;
+ 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 */
+ 331C807D294A63A400263BE5 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 97C146EA1CF9000F007C117D /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,
+ 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXTargetDependency section */
+ 331C8086294A63A400263BE5 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 97C146ED1CF9000F007C117D /* Runner */;
+ targetProxy = 331C8085294A63A400263BE5 /* 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;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
+ 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;
+ ENABLE_USER_SCRIPT_SANDBOXING = NO;
+ 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 = 12.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;
+ CLANG_ENABLE_MODULES = YES;
+ CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
+ CODE_SIGN_IDENTITY = "Apple Development";
+ CODE_SIGN_STYLE = Automatic;
+ CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
+ DEVELOPMENT_TEAM = 2X9AB296W2;
+ ENABLE_BITCODE = NO;
+ INFOPLIST_FILE = Runner/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = com.flutterbountyhunters.deeplinks.example;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ PROVISIONING_PROFILE_SPECIFIER = "";
+ SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
+ SWIFT_VERSION = 5.0;
+ VERSIONING_SYSTEM = "apple-generic";
+ };
+ name = Profile;
+ };
+ 331C8088294A63A400263BE5 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ BUNDLE_LOADER = "$(TEST_HOST)";
+ CODE_SIGN_STYLE = Automatic;
+ CURRENT_PROJECT_VERSION = 1;
+ GENERATE_INFOPLIST_FILE = YES;
+ MARKETING_VERSION = 1.0;
+ PRODUCT_BUNDLE_IDENTIFIER = com.flutterbountyhunters.deeplinks.example.exampleDeepLinks.RunnerTests;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ SWIFT_VERSION = 5.0;
+ TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
+ };
+ name = Debug;
+ };
+ 331C8089294A63A400263BE5 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ BUNDLE_LOADER = "$(TEST_HOST)";
+ CODE_SIGN_STYLE = Automatic;
+ CURRENT_PROJECT_VERSION = 1;
+ GENERATE_INFOPLIST_FILE = YES;
+ MARKETING_VERSION = 1.0;
+ PRODUCT_BUNDLE_IDENTIFIER = com.flutterbountyhunters.deeplinks.example.exampleDeepLinks.RunnerTests;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_VERSION = 5.0;
+ TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
+ };
+ name = Release;
+ };
+ 331C808A294A63A400263BE5 /* Profile */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ BUNDLE_LOADER = "$(TEST_HOST)";
+ CODE_SIGN_STYLE = Automatic;
+ CURRENT_PROJECT_VERSION = 1;
+ GENERATE_INFOPLIST_FILE = YES;
+ MARKETING_VERSION = 1.0;
+ PRODUCT_BUNDLE_IDENTIFIER = com.flutterbountyhunters.deeplinks.example.exampleDeepLinks.RunnerTests;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_VERSION = 5.0;
+ TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
+ };
+ name = Profile;
+ };
+ 97C147031CF9000F007C117D /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
+ 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;
+ ENABLE_USER_SCRIPT_SANDBOXING = NO;
+ 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 = 12.0;
+ MTL_ENABLE_DEBUG_INFO = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Debug;
+ };
+ 97C147041CF9000F007C117D /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
+ 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;
+ ENABLE_USER_SCRIPT_SANDBOXING = NO;
+ 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 = 12.0;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ SDKROOT = iphoneos;
+ SUPPORTED_PLATFORMS = iphoneos;
+ SWIFT_COMPILATION_MODE = wholemodule;
+ SWIFT_OPTIMIZATION_LEVEL = "-O";
+ TARGETED_DEVICE_FAMILY = "1,2";
+ VALIDATE_PRODUCT = YES;
+ };
+ name = Release;
+ };
+ 97C147061CF9000F007C117D /* Debug */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CLANG_ENABLE_MODULES = YES;
+ CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
+ CODE_SIGN_IDENTITY = "Apple Development";
+ CODE_SIGN_STYLE = Automatic;
+ CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
+ DEVELOPMENT_TEAM = 2X9AB296W2;
+ ENABLE_BITCODE = NO;
+ INFOPLIST_FILE = Runner/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = com.flutterbountyhunters.deeplinks.example;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ PROVISIONING_PROFILE_SPECIFIER = "";
+ SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ SWIFT_VERSION = 5.0;
+ VERSIONING_SYSTEM = "apple-generic";
+ };
+ name = Debug;
+ };
+ 97C147071CF9000F007C117D /* Release */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CLANG_ENABLE_MODULES = YES;
+ CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
+ CODE_SIGN_IDENTITY = "Apple Development";
+ CODE_SIGN_STYLE = Automatic;
+ CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
+ DEVELOPMENT_TEAM = 2X9AB296W2;
+ ENABLE_BITCODE = NO;
+ INFOPLIST_FILE = Runner/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = com.flutterbountyhunters.deeplinks.example;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ PROVISIONING_PROFILE_SPECIFIER = "";
+ SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
+ SWIFT_VERSION = 5.0;
+ VERSIONING_SYSTEM = "apple-generic";
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 331C8088294A63A400263BE5 /* Debug */,
+ 331C8089294A63A400263BE5 /* Release */,
+ 331C808A294A63A400263BE5 /* 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/flutter_test_runners/example_deep_links/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/packages/flutter_test_runners/example_deep_links/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 0000000..919434a
--- /dev/null
+++ b/packages/flutter_test_runners/example_deep_links/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,7 @@
+
+
+
+
+
diff --git a/packages/flutter_test_runners/example_deep_links/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/packages/flutter_test_runners/example_deep_links/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
new file mode 100644
index 0000000..18d9810
--- /dev/null
+++ b/packages/flutter_test_runners/example_deep_links/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
@@ -0,0 +1,8 @@
+
+
+
+
+ IDEDidComputeMac32BitWarning
+
+
+
diff --git a/packages/flutter_test_runners/example_deep_links/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/packages/flutter_test_runners/example_deep_links/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
new file mode 100644
index 0000000..f9b0d7c
--- /dev/null
+++ b/packages/flutter_test_runners/example_deep_links/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
@@ -0,0 +1,8 @@
+
+
+
+
+ PreviewsEnabled
+
+
+
diff --git a/packages/flutter_test_runners/example_deep_links/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/packages/flutter_test_runners/example_deep_links/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
new file mode 100644
index 0000000..8e3ca5d
--- /dev/null
+++ b/packages/flutter_test_runners/example_deep_links/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
@@ -0,0 +1,98 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/flutter_test_runners/example_deep_links/ios/Runner.xcworkspace/contents.xcworkspacedata b/packages/flutter_test_runners/example_deep_links/ios/Runner.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 0000000..1d526a1
--- /dev/null
+++ b/packages/flutter_test_runners/example_deep_links/ios/Runner.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,7 @@
+
+
+
+
+
diff --git a/packages/flutter_test_runners/example_deep_links/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/packages/flutter_test_runners/example_deep_links/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
new file mode 100644
index 0000000..18d9810
--- /dev/null
+++ b/packages/flutter_test_runners/example_deep_links/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
@@ -0,0 +1,8 @@
+
+
+
+
+ IDEDidComputeMac32BitWarning
+
+
+
diff --git a/packages/flutter_test_runners/example_deep_links/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/packages/flutter_test_runners/example_deep_links/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
new file mode 100644
index 0000000..f9b0d7c
--- /dev/null
+++ b/packages/flutter_test_runners/example_deep_links/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
@@ -0,0 +1,8 @@
+
+
+
+
+ PreviewsEnabled
+
+
+
diff --git a/packages/flutter_test_runners/example_deep_links/ios/Runner/AppDelegate.swift b/packages/flutter_test_runners/example_deep_links/ios/Runner/AppDelegate.swift
new file mode 100644
index 0000000..6266644
--- /dev/null
+++ b/packages/flutter_test_runners/example_deep_links/ios/Runner/AppDelegate.swift
@@ -0,0 +1,13 @@
+import Flutter
+import UIKit
+
+@main
+@objc class AppDelegate: FlutterAppDelegate {
+ override func application(
+ _ application: UIApplication,
+ didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
+ ) -> Bool {
+ GeneratedPluginRegistrant.register(with: self)
+ return super.application(application, didFinishLaunchingWithOptions: launchOptions)
+ }
+}
diff --git a/packages/flutter_test_runners/example_deep_links/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/packages/flutter_test_runners/example_deep_links/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json
new file mode 100644
index 0000000..d36b1fa
--- /dev/null
+++ b/packages/flutter_test_runners/example_deep_links/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/flutter_test_runners/example_deep_links/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/packages/flutter_test_runners/example_deep_links/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png
new file mode 100644
index 0000000..dc9ada4
Binary files /dev/null and b/packages/flutter_test_runners/example_deep_links/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png differ
diff --git a/packages/flutter_test_runners/example_deep_links/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/packages/flutter_test_runners/example_deep_links/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png
new file mode 100644
index 0000000..7353c41
Binary files /dev/null and b/packages/flutter_test_runners/example_deep_links/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png differ
diff --git a/packages/flutter_test_runners/example_deep_links/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/packages/flutter_test_runners/example_deep_links/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png
new file mode 100644
index 0000000..797d452
Binary files /dev/null and b/packages/flutter_test_runners/example_deep_links/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png differ
diff --git a/packages/flutter_test_runners/example_deep_links/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/packages/flutter_test_runners/example_deep_links/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png
new file mode 100644
index 0000000..6ed2d93
Binary files /dev/null and b/packages/flutter_test_runners/example_deep_links/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png differ
diff --git a/packages/flutter_test_runners/example_deep_links/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/packages/flutter_test_runners/example_deep_links/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png
new file mode 100644
index 0000000..4cd7b00
Binary files /dev/null and b/packages/flutter_test_runners/example_deep_links/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png differ
diff --git a/packages/flutter_test_runners/example_deep_links/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/packages/flutter_test_runners/example_deep_links/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png
new file mode 100644
index 0000000..fe73094
Binary files /dev/null and b/packages/flutter_test_runners/example_deep_links/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png differ
diff --git a/packages/flutter_test_runners/example_deep_links/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/packages/flutter_test_runners/example_deep_links/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png
new file mode 100644
index 0000000..321773c
Binary files /dev/null and b/packages/flutter_test_runners/example_deep_links/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png differ
diff --git a/packages/flutter_test_runners/example_deep_links/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/packages/flutter_test_runners/example_deep_links/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png
new file mode 100644
index 0000000..797d452
Binary files /dev/null and b/packages/flutter_test_runners/example_deep_links/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png differ
diff --git a/packages/flutter_test_runners/example_deep_links/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/packages/flutter_test_runners/example_deep_links/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png
new file mode 100644
index 0000000..502f463
Binary files /dev/null and b/packages/flutter_test_runners/example_deep_links/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png differ
diff --git a/packages/flutter_test_runners/example_deep_links/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/packages/flutter_test_runners/example_deep_links/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png
new file mode 100644
index 0000000..0ec3034
Binary files /dev/null and b/packages/flutter_test_runners/example_deep_links/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png differ
diff --git a/packages/flutter_test_runners/example_deep_links/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/packages/flutter_test_runners/example_deep_links/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png
new file mode 100644
index 0000000..0ec3034
Binary files /dev/null and b/packages/flutter_test_runners/example_deep_links/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png differ
diff --git a/packages/flutter_test_runners/example_deep_links/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/packages/flutter_test_runners/example_deep_links/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png
new file mode 100644
index 0000000..e9f5fea
Binary files /dev/null and b/packages/flutter_test_runners/example_deep_links/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png differ
diff --git a/packages/flutter_test_runners/example_deep_links/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/packages/flutter_test_runners/example_deep_links/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png
new file mode 100644
index 0000000..84ac32a
Binary files /dev/null and b/packages/flutter_test_runners/example_deep_links/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png differ
diff --git a/packages/flutter_test_runners/example_deep_links/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/packages/flutter_test_runners/example_deep_links/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
new file mode 100644
index 0000000..8953cba
Binary files /dev/null and b/packages/flutter_test_runners/example_deep_links/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png differ
diff --git a/packages/flutter_test_runners/example_deep_links/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/packages/flutter_test_runners/example_deep_links/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
new file mode 100644
index 0000000..0467bf1
Binary files /dev/null and b/packages/flutter_test_runners/example_deep_links/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png differ
diff --git a/packages/flutter_test_runners/example_deep_links/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/packages/flutter_test_runners/example_deep_links/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json
new file mode 100644
index 0000000..0bedcf2
--- /dev/null
+++ b/packages/flutter_test_runners/example_deep_links/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/flutter_test_runners/example_deep_links/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png b/packages/flutter_test_runners/example_deep_links/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
new file mode 100644
index 0000000..9da19ea
Binary files /dev/null and b/packages/flutter_test_runners/example_deep_links/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png differ
diff --git a/packages/flutter_test_runners/example_deep_links/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/packages/flutter_test_runners/example_deep_links/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
new file mode 100644
index 0000000..9da19ea
Binary files /dev/null and b/packages/flutter_test_runners/example_deep_links/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png differ
diff --git a/packages/flutter_test_runners/example_deep_links/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/packages/flutter_test_runners/example_deep_links/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png
new file mode 100644
index 0000000..9da19ea
Binary files /dev/null and b/packages/flutter_test_runners/example_deep_links/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png differ
diff --git a/packages/flutter_test_runners/example_deep_links/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/packages/flutter_test_runners/example_deep_links/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md
new file mode 100644
index 0000000..89c2725
--- /dev/null
+++ b/packages/flutter_test_runners/example_deep_links/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/flutter_test_runners/example_deep_links/ios/Runner/Base.lproj/LaunchScreen.storyboard b/packages/flutter_test_runners/example_deep_links/ios/Runner/Base.lproj/LaunchScreen.storyboard
new file mode 100644
index 0000000..f2e259c
--- /dev/null
+++ b/packages/flutter_test_runners/example_deep_links/ios/Runner/Base.lproj/LaunchScreen.storyboard
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/flutter_test_runners/example_deep_links/ios/Runner/Base.lproj/Main.storyboard b/packages/flutter_test_runners/example_deep_links/ios/Runner/Base.lproj/Main.storyboard
new file mode 100644
index 0000000..f3c2851
--- /dev/null
+++ b/packages/flutter_test_runners/example_deep_links/ios/Runner/Base.lproj/Main.storyboard
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/flutter_test_runners/example_deep_links/ios/Runner/Info.plist b/packages/flutter_test_runners/example_deep_links/ios/Runner/Info.plist
new file mode 100644
index 0000000..9fa709d
--- /dev/null
+++ b/packages/flutter_test_runners/example_deep_links/ios/Runner/Info.plist
@@ -0,0 +1,49 @@
+
+
+
+
+ CADisableMinimumFrameDurationOnPhone
+
+ CFBundleDevelopmentRegion
+ $(DEVELOPMENT_LANGUAGE)
+ CFBundleDisplayName
+ Example Deep Links
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ example_deep_links
+ CFBundlePackageType
+ APPL
+ CFBundleShortVersionString
+ $(FLUTTER_BUILD_NAME)
+ CFBundleSignature
+ ????
+ CFBundleVersion
+ $(FLUTTER_BUILD_NUMBER)
+ LSRequiresIPhoneOS
+
+ UIApplicationSupportsIndirectInputEvents
+
+ UILaunchStoryboardName
+ LaunchScreen
+ UIMainStoryboardFile
+ Main
+ UISupportedInterfaceOrientations
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+ UISupportedInterfaceOrientations~ipad
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationPortraitUpsideDown
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+
+
diff --git a/packages/flutter_test_runners/example_deep_links/ios/Runner/Runner-Bridging-Header.h b/packages/flutter_test_runners/example_deep_links/ios/Runner/Runner-Bridging-Header.h
new file mode 100644
index 0000000..308a2a5
--- /dev/null
+++ b/packages/flutter_test_runners/example_deep_links/ios/Runner/Runner-Bridging-Header.h
@@ -0,0 +1 @@
+#import "GeneratedPluginRegistrant.h"
diff --git a/packages/flutter_test_runners/example_deep_links/ios/Runner/Runner.entitlements b/packages/flutter_test_runners/example_deep_links/ios/Runner/Runner.entitlements
new file mode 100644
index 0000000..c16c78e
--- /dev/null
+++ b/packages/flutter_test_runners/example_deep_links/ios/Runner/Runner.entitlements
@@ -0,0 +1,10 @@
+
+
+
+
+ com.apple.developer.associated-domains
+
+ applinks:deeplinks.flutterbountyhunters.com
+
+
+
diff --git a/packages/flutter_test_runners/example_deep_links/ios/RunnerTests/RunnerTests.swift b/packages/flutter_test_runners/example_deep_links/ios/RunnerTests/RunnerTests.swift
new file mode 100644
index 0000000..86a7c3b
--- /dev/null
+++ b/packages/flutter_test_runners/example_deep_links/ios/RunnerTests/RunnerTests.swift
@@ -0,0 +1,12 @@
+import Flutter
+import UIKit
+import XCTest
+
+class RunnerTests: XCTestCase {
+
+ func testExample() {
+ // If you add code to the Runner application, consider adding tests here.
+ // See https://developer.apple.com/documentation/xctest for more information about using XCTest.
+ }
+
+}
diff --git a/packages/flutter_test_runners/example_deep_links/lib/main.dart b/packages/flutter_test_runners/example_deep_links/lib/main.dart
new file mode 100644
index 0000000..cf26659
--- /dev/null
+++ b/packages/flutter_test_runners/example_deep_links/lib/main.dart
@@ -0,0 +1,129 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_driver/driver_extension.dart';
+import 'package:go_router/go_router.dart';
+
+void main() {
+ enableFlutterDriverExtension();
+
+ runApp(const MyApp());
+}
+
+class MyApp extends StatelessWidget {
+ const MyApp({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ return MaterialApp.router(
+ title: 'Flutter Demo',
+ theme: ThemeData(
+ colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
+ useMaterial3: true,
+ ),
+ routerConfig: router,
+ );
+ }
+}
+
+final router = GoRouter(
+ routes: [
+ GoRoute(
+ path: '/',
+ builder: (_, __) => Scaffold(
+ appBar: AppBar(title: const Text('Home Screen')),
+ ),
+ routes: [
+ GoRoute(
+ path: 'signup',
+ builder: (_, __) => Scaffold(
+ appBar: AppBar(title: const Text('Sign Up')),
+ ),
+ ),
+ GoRoute(
+ path: 'user/profile',
+ builder: (_, __) => Scaffold(
+ appBar: AppBar(title: const Text('User Profile')),
+ ),
+ ),
+ ],
+ ),
+ ],
+);
+
+class MyHomePage extends StatefulWidget {
+ const MyHomePage({super.key, required this.title});
+
+ final String title;
+
+ @override
+ State createState() => _MyHomePageState();
+}
+
+class _MyHomePageState extends State {
+ int _counter = 0;
+
+ void _incrementCounter() {
+ setState(() {
+ // This call to setState tells the Flutter framework that something has
+ // changed in this State, which causes it to rerun the build method below
+ // so that the display can reflect the updated values. If we changed
+ // _counter without calling setState(), then the build method would not be
+ // called again, and so nothing would appear to happen.
+ _counter++;
+ });
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ // This method is rerun every time setState is called, for instance as done
+ // by the _incrementCounter method above.
+ //
+ // The Flutter framework has been optimized to make rerunning build methods
+ // fast, so that you can just rebuild anything that needs updating rather
+ // than having to individually change instances of widgets.
+ return Scaffold(
+ appBar: AppBar(
+ // TRY THIS: Try changing the color here to a specific color (to
+ // Colors.amber, perhaps?) and trigger a hot reload to see the AppBar
+ // change color while the other colors stay the same.
+ backgroundColor: Theme.of(context).colorScheme.inversePrimary,
+ // Here we take the value from the MyHomePage object that was created by
+ // the App.build method, and use it to set our appbar title.
+ title: Text(widget.title),
+ ),
+ body: Center(
+ // Center is a layout widget. It takes a single child and positions it
+ // in the middle of the parent.
+ child: Column(
+ // Column is also a layout widget. It takes a list of children and
+ // arranges them vertically. By default, it sizes itself to fit its
+ // children horizontally, and tries to be as tall as its parent.
+ //
+ // Column has various properties to control how it sizes itself and
+ // how it positions its children. Here we use mainAxisAlignment to
+ // center the children vertically; the main axis here is the vertical
+ // axis because Columns are vertical (the cross axis would be
+ // horizontal).
+ //
+ // TRY THIS: Invoke "debug painting" (choose the "Toggle Debug Paint"
+ // action in the IDE, or press "p" in the console), to see the
+ // wireframe for each widget.
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ const Text(
+ 'You have pushed the button this many times:',
+ ),
+ Text(
+ '$_counter',
+ style: Theme.of(context).textTheme.headlineMedium,
+ ),
+ ],
+ ),
+ ),
+ floatingActionButton: FloatingActionButton(
+ onPressed: _incrementCounter,
+ tooltip: 'Increment',
+ child: const Icon(Icons.add),
+ ), // This trailing comma makes auto-formatting nicer for build methods.
+ );
+ }
+}
diff --git a/packages/flutter_test_runners/example_deep_links/pubspec.lock b/packages/flutter_test_runners/example_deep_links/pubspec.lock
new file mode 100644
index 0000000..f999e31
--- /dev/null
+++ b/packages/flutter_test_runners/example_deep_links/pubspec.lock
@@ -0,0 +1,560 @@
+# Generated by pub
+# See https://dart.dev/tools/pub/glossary#lockfile
+packages:
+ _fe_analyzer_shared:
+ dependency: transitive
+ description:
+ name: _fe_analyzer_shared
+ sha256: "16e298750b6d0af7ce8a3ba7c18c69c3785d11b15ec83f6dcd0ad2a0009b3cab"
+ url: "https://pub.dev"
+ source: hosted
+ version: "76.0.0"
+ _macros:
+ dependency: transitive
+ description: dart
+ source: sdk
+ version: "0.3.3"
+ analyzer:
+ dependency: transitive
+ description:
+ name: analyzer
+ sha256: "1f14db053a8c23e260789e9b0980fa27f2680dd640932cae5e1137cce0e46e1e"
+ url: "https://pub.dev"
+ source: hosted
+ version: "6.11.0"
+ args:
+ dependency: transitive
+ description:
+ name: args
+ sha256: bf9f5caeea8d8fe6721a9c358dd8a5c1947b27f1cfaa18b39c301273594919e6
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.6.0"
+ async:
+ dependency: transitive
+ description:
+ name: async
+ sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.11.0"
+ boolean_selector:
+ dependency: transitive
+ description:
+ name: boolean_selector
+ sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.1.1"
+ characters:
+ dependency: transitive
+ description:
+ name: characters
+ sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.3.0"
+ clock:
+ dependency: transitive
+ description:
+ name: clock
+ sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.1.1"
+ collection:
+ dependency: transitive
+ description:
+ name: collection
+ sha256: a1ace0a119f20aabc852d165077c036cd864315bd99b7eaa10a60100341941bf
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.19.0"
+ convert:
+ dependency: transitive
+ description:
+ name: convert
+ sha256: b30acd5944035672bc15c6b7a8b47d773e41e2f17de064350988c5d02adb1c68
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.1.2"
+ coverage:
+ dependency: transitive
+ description:
+ name: coverage
+ sha256: e3493833ea012784c740e341952298f1cc77f1f01b1bbc3eb4eecf6984fb7f43
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.11.1"
+ crypto:
+ dependency: transitive
+ description:
+ name: crypto
+ sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.0.6"
+ cupertino_icons:
+ dependency: "direct main"
+ description:
+ name: cupertino_icons
+ sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.0.8"
+ fake_async:
+ dependency: transitive
+ description:
+ name: fake_async
+ sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.3.1"
+ file:
+ dependency: transitive
+ description:
+ name: file
+ sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c"
+ url: "https://pub.dev"
+ source: hosted
+ version: "7.0.0"
+ flutter:
+ dependency: "direct main"
+ description: flutter
+ source: sdk
+ version: "0.0.0"
+ flutter_driver:
+ dependency: "direct main"
+ description: flutter
+ source: sdk
+ version: "0.0.0"
+ flutter_lints:
+ dependency: "direct dev"
+ description:
+ name: flutter_lints
+ sha256: "5398f14efa795ffb7a33e9b6a08798b26a180edac4ad7db3f231e40f82ce11e1"
+ url: "https://pub.dev"
+ source: hosted
+ version: "5.0.0"
+ flutter_test:
+ dependency: "direct dev"
+ description: flutter
+ source: sdk
+ version: "0.0.0"
+ flutter_test_runners:
+ dependency: "direct dev"
+ description:
+ path: ".."
+ relative: true
+ source: path
+ version: "0.0.4"
+ flutter_web_plugins:
+ dependency: transitive
+ description: flutter
+ source: sdk
+ version: "0.0.0"
+ frontend_server_client:
+ dependency: transitive
+ description:
+ name: frontend_server_client
+ sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694
+ url: "https://pub.dev"
+ source: hosted
+ version: "4.0.0"
+ fuchsia_remote_debug_protocol:
+ dependency: transitive
+ description: flutter
+ source: sdk
+ version: "0.0.0"
+ glob:
+ dependency: transitive
+ description:
+ name: glob
+ sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.1.2"
+ go_router:
+ dependency: "direct main"
+ description:
+ name: go_router
+ sha256: "2fd11229f59e23e967b0775df8d5948a519cd7e1e8b6e849729e010587b46539"
+ url: "https://pub.dev"
+ source: hosted
+ version: "14.6.2"
+ http_multi_server:
+ dependency: transitive
+ description:
+ name: http_multi_server
+ sha256: aa6199f908078bb1c5efb8d8638d4ae191aac11b311132c3ef48ce352fb52ef8
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.2.2"
+ http_parser:
+ dependency: transitive
+ description:
+ name: http_parser
+ sha256: "76d306a1c3afb33fe82e2bbacad62a61f409b5634c915fceb0d799de1a913360"
+ url: "https://pub.dev"
+ source: hosted
+ version: "4.1.1"
+ io:
+ dependency: transitive
+ description:
+ name: io
+ sha256: dfd5a80599cf0165756e3181807ed3e77daf6dd4137caaad72d0b7931597650b
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.0.5"
+ js:
+ dependency: transitive
+ description:
+ name: js
+ sha256: c1b2e9b5ea78c45e1a0788d29606ba27dc5f71f019f32ca5140f61ef071838cf
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.7.1"
+ leak_tracker:
+ dependency: transitive
+ description:
+ name: leak_tracker
+ sha256: "7bb2830ebd849694d1ec25bf1f44582d6ac531a57a365a803a6034ff751d2d06"
+ url: "https://pub.dev"
+ source: hosted
+ version: "10.0.7"
+ leak_tracker_flutter_testing:
+ dependency: transitive
+ description:
+ name: leak_tracker_flutter_testing
+ sha256: "9491a714cca3667b60b5c420da8217e6de0d1ba7a5ec322fab01758f6998f379"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.0.8"
+ leak_tracker_testing:
+ dependency: transitive
+ description:
+ name: leak_tracker_testing
+ sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.0.1"
+ lints:
+ dependency: transitive
+ description:
+ name: lints
+ sha256: c35bb79562d980e9a453fc715854e1ed39e24e7d0297a880ef54e17f9874a9d7
+ url: "https://pub.dev"
+ source: hosted
+ version: "5.1.1"
+ logging:
+ dependency: transitive
+ description:
+ name: logging
+ sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.3.0"
+ macros:
+ dependency: transitive
+ description:
+ name: macros
+ sha256: "1d9e801cd66f7ea3663c45fc708450db1fa57f988142c64289142c9b7ee80656"
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.1.3-main.0"
+ matcher:
+ dependency: transitive
+ description:
+ name: matcher
+ sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.12.16+1"
+ material_color_utilities:
+ dependency: transitive
+ description:
+ name: material_color_utilities
+ sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.11.1"
+ meta:
+ dependency: transitive
+ description:
+ name: meta
+ sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.15.0"
+ mime:
+ dependency: transitive
+ description:
+ name: mime
+ sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.0.0"
+ node_preamble:
+ dependency: transitive
+ description:
+ name: node_preamble
+ sha256: "6e7eac89047ab8a8d26cf16127b5ed26de65209847630400f9aefd7cd5c730db"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.0.2"
+ package_config:
+ dependency: transitive
+ description:
+ name: package_config
+ sha256: "92d4488434b520a62570293fbd33bb556c7d49230791c1b4bbd973baf6d2dc67"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.1.1"
+ path:
+ dependency: transitive
+ description:
+ name: path
+ sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.9.0"
+ platform:
+ dependency: transitive
+ description:
+ name: platform
+ sha256: "9b71283fc13df574056616011fb138fd3b793ea47cc509c189a6c3fa5f8a1a65"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.1.5"
+ pool:
+ dependency: transitive
+ description:
+ name: pool
+ sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.5.1"
+ process:
+ dependency: transitive
+ description:
+ name: process
+ sha256: "21e54fd2faf1b5bdd5102afd25012184a6793927648ea81eea80552ac9405b32"
+ url: "https://pub.dev"
+ source: hosted
+ version: "5.0.2"
+ pub_semver:
+ dependency: transitive
+ description:
+ name: pub_semver
+ sha256: "7b3cfbf654f3edd0c6298ecd5be782ce997ddf0e00531b9464b55245185bbbbd"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.1.5"
+ shelf:
+ dependency: transitive
+ description:
+ name: shelf
+ sha256: e7dd780a7ffb623c57850b33f43309312fc863fb6aa3d276a754bb299839ef12
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.4.2"
+ shelf_packages_handler:
+ dependency: transitive
+ description:
+ name: shelf_packages_handler
+ sha256: "89f967eca29607c933ba9571d838be31d67f53f6e4ee15147d5dc2934fee1b1e"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.0.2"
+ shelf_static:
+ dependency: transitive
+ description:
+ name: shelf_static
+ sha256: c87c3875f91262785dade62d135760c2c69cb217ac759485334c5857ad89f6e3
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.1.3"
+ shelf_web_socket:
+ dependency: transitive
+ description:
+ name: shelf_web_socket
+ sha256: cc36c297b52866d203dbf9332263c94becc2fe0ceaa9681d07b6ef9807023b67
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.0.1"
+ sky_engine:
+ dependency: transitive
+ description: flutter
+ source: sdk
+ version: "0.0.0"
+ source_map_stack_trace:
+ dependency: transitive
+ description:
+ name: source_map_stack_trace
+ sha256: c0713a43e323c3302c2abe2a1cc89aa057a387101ebd280371d6a6c9fa68516b
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.1.2"
+ source_maps:
+ dependency: transitive
+ description:
+ name: source_maps
+ sha256: "190222579a448b03896e0ca6eca5998fa810fda630c1d65e2f78b3f638f54812"
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.10.13"
+ source_span:
+ dependency: transitive
+ description:
+ name: source_span
+ sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.10.0"
+ stack_trace:
+ dependency: transitive
+ description:
+ name: stack_trace
+ sha256: "9f47fd3630d76be3ab26f0ee06d213679aa425996925ff3feffdec504931c377"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.12.0"
+ stream_channel:
+ dependency: transitive
+ description:
+ name: stream_channel
+ sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.1.2"
+ string_scanner:
+ dependency: transitive
+ description:
+ name: string_scanner
+ sha256: "688af5ed3402a4bde5b3a6c15fd768dbf2621a614950b17f04626c431ab3c4c3"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.3.0"
+ sync_http:
+ dependency: transitive
+ description:
+ name: sync_http
+ sha256: "7f0cd72eca000d2e026bcd6f990b81d0ca06022ef4e32fb257b30d3d1014a961"
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.3.1"
+ term_glyph:
+ dependency: transitive
+ description:
+ name: term_glyph
+ sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.2.1"
+ test:
+ dependency: "direct dev"
+ description:
+ name: test
+ sha256: "713a8789d62f3233c46b4a90b174737b2c04cb6ae4500f2aa8b1be8f03f5e67f"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.25.8"
+ test_api:
+ dependency: transitive
+ description:
+ name: test_api
+ sha256: "664d3a9a64782fcdeb83ce9c6b39e78fd2971d4e37827b9b06c3aa1edc5e760c"
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.7.3"
+ test_core:
+ dependency: transitive
+ description:
+ name: test_core
+ sha256: "12391302411737c176b0b5d6491f466b0dd56d4763e347b6714efbaa74d7953d"
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.6.5"
+ typed_data:
+ dependency: transitive
+ description:
+ name: typed_data
+ sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.4.0"
+ vector_math:
+ dependency: transitive
+ description:
+ name: vector_math
+ sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.1.4"
+ vm_service:
+ dependency: transitive
+ description:
+ name: vm_service
+ sha256: f6be3ed8bd01289b34d679c2b62226f63c0e69f9fd2e50a6b3c1c729a961041b
+ url: "https://pub.dev"
+ source: hosted
+ version: "14.3.0"
+ watcher:
+ dependency: transitive
+ description:
+ name: watcher
+ sha256: "69da27e49efa56a15f8afe8f4438c4ec02eff0a117df1b22ea4aad194fe1c104"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.1.1"
+ web:
+ dependency: transitive
+ description:
+ name: web
+ sha256: cd3543bd5798f6ad290ea73d210f423502e71900302dde696f8bff84bf89a1cb
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.1.0"
+ web_socket:
+ dependency: transitive
+ description:
+ name: web_socket
+ sha256: "3c12d96c0c9a4eec095246debcea7b86c0324f22df69893d538fcc6f1b8cce83"
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.1.6"
+ web_socket_channel:
+ dependency: transitive
+ description:
+ name: web_socket_channel
+ sha256: "9f187088ed104edd8662ca07af4b124465893caf063ba29758f97af57e61da8f"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.0.1"
+ webdriver:
+ dependency: transitive
+ description:
+ name: webdriver
+ sha256: "3d773670966f02a646319410766d3b5e1037efb7f07cc68f844d5e06cd4d61c8"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.0.4"
+ webkit_inspection_protocol:
+ dependency: transitive
+ description:
+ name: webkit_inspection_protocol
+ sha256: "87d3f2333bb240704cd3f1c6b5b7acd8a10e7f0bc28c28dcf14e782014f4a572"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.2.1"
+ yaml:
+ dependency: transitive
+ description:
+ name: yaml
+ sha256: b9da305ac7c39faa3f030eccd175340f968459dae4af175130b3fc47e40d76ce
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.1.3"
+sdks:
+ dart: ">=3.6.0 <4.0.0"
+ flutter: ">=3.19.0"
diff --git a/packages/flutter_test_runners/example_deep_links/pubspec.yaml b/packages/flutter_test_runners/example_deep_links/pubspec.yaml
new file mode 100644
index 0000000..b21a890
--- /dev/null
+++ b/packages/flutter_test_runners/example_deep_links/pubspec.yaml
@@ -0,0 +1,65 @@
+name: example_deep_links
+description: "Example app for testing deep links."
+publish_to: 'none' # Remove this line if you wish to publish to pub.dev
+
+version: 1.0.0+1
+
+environment:
+ sdk: ^3.6.0
+
+dependencies:
+ flutter:
+ sdk: flutter
+ flutter_driver:
+ sdk: flutter
+
+ cupertino_icons: ^1.0.8
+ go_router: ^14.6.2
+
+dev_dependencies:
+ flutter_test:
+ sdk: flutter
+ flutter_lints: ^5.0.0
+
+ test: any
+
+ flutter_test_runners:
+ path: ../
+
+flutter:
+
+ # The following line ensures that the Material Icons font is
+ # included with your application, so that you can use the icons in
+ # the material Icons class.
+ uses-material-design: true
+
+ # To add assets to your application, add an assets section, like this:
+ # assets:
+ # - images/a_dot_burr.jpeg
+ # - images/a_dot_ham.jpeg
+
+ # An image asset can refer to one or more resolution-specific "variants", see
+ # https://flutter.dev/to/resolution-aware-images
+
+ # For details regarding adding assets from package dependencies, see
+ # https://flutter.dev/to/asset-from-package
+
+ # To add custom fonts to your application, add a fonts section here,
+ # in this "flutter" section. Each entry in this list should have a
+ # "family" key with the font family name, and a "fonts" key with a
+ # list giving the asset and other descriptors for the font. For
+ # example:
+ # fonts:
+ # - family: Schyler
+ # fonts:
+ # - asset: fonts/Schyler-Regular.ttf
+ # - asset: fonts/Schyler-Italic.ttf
+ # style: italic
+ # - family: Trajan Pro
+ # fonts:
+ # - asset: fonts/TrajanPro.ttf
+ # - asset: fonts/TrajanPro_Bold.ttf
+ # weight: 700
+ #
+ # For details regarding fonts from package dependencies,
+ # see https://flutter.dev/to/font-from-package
diff --git a/packages/flutter_test_runners/example_deep_links/test_driver/deep_link_android_test.dart b/packages/flutter_test_runners/example_deep_links/test_driver/deep_link_android_test.dart
new file mode 100644
index 0000000..e3d16a2
--- /dev/null
+++ b/packages/flutter_test_runners/example_deep_links/test_driver/deep_link_android_test.dart
@@ -0,0 +1,42 @@
+import 'package:flutter_driver/flutter_driver.dart';
+import 'package:flutter_test_runners/flutter_test_runners.dart';
+import 'package:test/test.dart';
+
+void main() {
+ const appPackage = "com.flutterbountyhunters.deeplinks.example";
+
+ // Command you can use to directly check a deep link:
+ // adb shell am start -W -a android.intent.action.VIEW -d "app://deeplinks.flutterbountyhunters.com/user/profile" com.flutterbountyhunters.deeplinks.example
+
+ group("Deep link launches app > Android >", () {
+ testDeepLinkAndroidAppLaunch(
+ "home screen",
+ appPackage: appPackage,
+ deepLink: "app://deeplinks.flutterbountyhunters.com",
+ (driver) async {
+ await driver.waitFor(find.text("Home Screen"));
+ await Future.delayed(const Duration(seconds: 3));
+ },
+ );
+
+ testDeepLinkAndroidAppLaunch(
+ "sign-up screen",
+ appPackage: appPackage,
+ deepLink: "app://deeplinks.flutterbountyhunters.com/signup",
+ (driver) async {
+ await driver.waitFor(find.text("Sign Up"));
+ await Future.delayed(const Duration(seconds: 3));
+ },
+ );
+
+ testDeepLinkAndroidAppLaunch(
+ "profile screen",
+ appPackage: appPackage,
+ deepLink: "app://deeplinks.flutterbountyhunters.com/user/profile",
+ (driver) async {
+ await driver.waitFor(find.text("User Profile"));
+ await Future.delayed(const Duration(seconds: 3));
+ },
+ );
+ });
+}
diff --git a/packages/flutter_test_runners/example_deep_links/test_driver/deep_link_ios_test.dart b/packages/flutter_test_runners/example_deep_links/test_driver/deep_link_ios_test.dart
new file mode 100644
index 0000000..05c849c
--- /dev/null
+++ b/packages/flutter_test_runners/example_deep_links/test_driver/deep_link_ios_test.dart
@@ -0,0 +1,152 @@
+import 'package:flutter_driver/flutter_driver.dart';
+import 'package:flutter_test_runners/flutter_test_runners.dart';
+import 'package:test/test.dart';
+
+void main() {
+ const appBundleId = "com.flutterbountyhunters.deeplinks.example";
+
+ // Command you can use to directly check a Universal Link:
+ // xcrun simctl openurl booted https://deeplinks.flutterbountyhunters.com
+
+ group("Deep link launches app > iOS >", () {
+ // test("xcrun sanity check", () async {
+ // print("Running xcrun Process sanity check.");
+ //
+ // // print("Env variables:");
+ // // print(Process.runSync('env', []).stdout);
+ //
+ // print("Running the command...");
+ // final result = await Process.run(
+ // "sh",
+ // [
+ // "-c",
+ // "xcrun",
+ // "simctl",
+ // // "list",
+ // // "--verbose",
+ // "get_app_container",
+ // "booted",
+ // "com.flutterbountyhunters.deeplinks.example",
+ // ],
+ // );
+ // // process.stdout.transform(utf8.decoder).listen((data) {
+ // // print("STDOUT:\n$data");
+ // // });
+ // // process.stderr.transform(utf8.decoder).listen((data) {
+ // // print("STDERR:\n$data");
+ // // });
+ // // print("The process started...");
+ // // print("Closing stdin");
+ // // process.stdin.close();
+ // // print("Waiting for exit code...");
+ // // final exitCode = await process.exitCode;
+ // // print("The xcrun call returned with exit code: $exitCode");
+ // print("The xcrun call returned with exit code: ${result.exitCode}");
+ // });
+
+ // test("Send terminate command to simulator", () async {
+ // print("Running device list command:");
+ // final result1 = await Process.run(
+ // "sh",
+ // [
+ // "-c",
+ // "xcrun simctl list",
+ // ],
+ // );
+ // print("result1: ${result1.exitCode}");
+ // print("");
+ //
+ // print("Running get_app_container command:");
+ // final result2 = await Process.run(
+ // "sh",
+ // [
+ // "-c",
+ // "xcrun simctl get_app_container booted com.flutterbountyhunters.deeplinks.example",
+ // ],
+ // );
+ // print("result2: ${result2.exitCode}");
+ // print("");
+ //
+ // //--------
+ // print("Sending xcrun simctl terminate command...");
+ //
+ // // CI Timeout
+ // // final process = await Process.start(
+ // // "xcrun",
+ // // ["simctl", "terminate", "booted", "'$appBundleId'"],
+ // // runInShell: true,
+ // // );
+ //
+ // // CI Timeout
+ // // final process = await Process.start(
+ // // "xcrun",
+ // // ["simctl", "terminate", "booted", "'$appBundleId'"],
+ // // );
+ //
+ // // CI Timeout
+ // // final process = await Process.start(
+ // // "sh",
+ // // ["-c", "xcrun simctl terminate booted '$appBundleId'"],
+ // // );
+ // //
+ // // CI Timeout
+ // // final result = await Process.run(
+ // // "sh",
+ // // ["-c", "xcrun simctl terminate booted '$appBundleId'"],
+ // // );
+ // // print("Exit code: ${result.exitCode}");
+ //
+ // // CI Timeout
+ // // final script = '''
+ // // #!/bin/bash
+ // // xcrun simctl terminate booted $appBundleId
+ // // ''';
+ // // final tempFile = File('/tmp/temp_script.sh');
+ // // await tempFile.writeAsString(script);
+ // // await Process.run('chmod', ['+x', tempFile.path]);
+ // // final process = await Process.start('/bin/bash', [tempFile.path]);
+ // //
+ // // print("terminate command process was started");
+ // //
+ // // process.stdin.close();
+ // //
+ // // stdout.addStream(process.stdout);
+ // // stderr.addStream(process.stderr);
+ // //
+ // // print("Waiting for exit code...");
+ // // final exitCode = await process.exitCode;
+ // // print("Killed app - exit code: $exitCode");
+ // });
+
+ testDeepLinkIosAppLaunch(
+ "home screen",
+ appBundleId: appBundleId,
+ deepLink: "https://deeplinks.flutterbountyhunters.com",
+ verbose: true,
+ (driver) async {
+ await driver.waitFor(find.text("Home Screen"));
+ await Future.delayed(const Duration(seconds: 3));
+ },
+ );
+
+ // testDeepLinkIosAppLaunch(
+ // "sign-up screen",
+ // appBundleId: appBundleId,
+ // deepLink: "https://deeplinks.flutterbountyhunters.com/signup",
+ // (driver) async {
+ // await driver.waitFor(find.text("Sign Up"));
+ // await Future.delayed(const Duration(seconds: 3));
+ // },
+ // );
+ //
+ // testDeepLinkIosAppLaunch(
+ // "profile screen",
+ // appBundleId: appBundleId,
+ // deepLink: "https://deeplinks.flutterbountyhunters.com/user/profile",
+ // (driver) async {
+ // await driver.waitFor(find.text("User Profile"));
+ // await Future.delayed(const Duration(seconds: 3));
+ // },
+ // );
+ });
+}
diff --git a/packages/flutter_test_runners/lib/flutter_test_runners.dart b/packages/flutter_test_runners/lib/flutter_test_runners.dart
index 53a51c8..6655eaa 100644
--- a/packages/flutter_test_runners/lib/flutter_test_runners.dart
+++ b/packages/flutter_test_runners/lib/flutter_test_runners.dart
@@ -2,3 +2,6 @@ library flutter_test_runners;
export 'src/platform_messages.dart';
export 'src/platform_runners.dart';
+
+export 'src/deep_links/deep_links_android.dart';
+export 'src/deep_links/deep_links_ios.dart';
diff --git a/packages/flutter_test_runners/lib/src/deep_links/deep_links_android.dart b/packages/flutter_test_runners/lib/src/deep_links/deep_links_android.dart
new file mode 100644
index 0000000..85da259
--- /dev/null
+++ b/packages/flutter_test_runners/lib/src/deep_links/deep_links_android.dart
@@ -0,0 +1,196 @@
+import 'dart:convert';
+
+import 'package:flutter_driver/flutter_driver.dart';
+import 'package:flutter_test_runners/src/platform_comms/android/adb.dart';
+import 'package:logging/logging.dart';
+import 'package:test/test.dart';
+import 'package:vm_service/vm_service.dart';
+import 'package:vm_service/vm_service_io.dart';
+
+/// A test that runs after launching the Android app with the given
+/// [appPackage], with the given [deepLink].
+///
+/// The test implementation is defined by the caller within [testRunner].
+/// The [testRunner] works the same way as a typical `test()` callback,
+/// except that the [testRunner] is given a [FlutterDriver] to inspect
+/// the app.
+///
+/// Tests that launch apps with deep links must use a [FlutterDriver],
+/// instead of a [WidgetTester], because [WidgetTester]s require building
+/// and launching the app with instrumentation. Launching an app with a
+/// deep link doesn't have instrumentation. Instead, the host machine
+/// users the [FlutterDriver] to talk to the running app.
+void testDeepLinkAndroidAppLaunch(
+ String description,
+ Future Function(FlutterDriver driver) testRunner, {
+ required String appPackage,
+ required String deepLink,
+ bool verbose = false,
+}) {
+ test(description, () async {
+ _initLogs(verbose);
+ _log.info("Running deep link test driver...");
+
+ // Pre-emptively the kill the app, in case it's already running.
+ await Adb.killApp(appPackage);
+
+ late final FlutterDriver? driver;
+ addTearDown(() async {
+ _log.info("Cleaning up after the test");
+ // Dispose the FlutterDriver connection.
+ driver?.serviceClient.dispose();
+
+ // Kill the app when we're done.
+ await Adb.killApp(appPackage);
+ });
+
+ // Ensure the app isn't running yet.
+ expect(await Adb.isAppRunning(appPackage), isFalse);
+
+ // Clear previous logcat messages so we don't try to connect to a previous
+ // Dart VM service listing.
+ await Adb.clearLogcat();
+
+ // Listen to logcat to find the Dart VM service for the running app.
+ String? dartVmService;
+ await Adb.listenToAdbForFlutterLogs(onLog: (data) {
+ if (data.contains("Dart VM service")) {
+ _log.info("Found Dart VM log:\n$data");
+
+ final regex = RegExp(r'.*Dart VM service.*(http[s]?://[^\s]+)');
+ final httpUrl = Uri.parse(regex.firstMatch(data)!.group(1)!);
+
+ dartVmService = Uri(scheme: "ws", host: httpUrl.host, port: httpUrl.port, path: "${httpUrl.path}ws").toString();
+ }
+ }, onError: (error) {
+ _log.shout("LOGCAT ERROR:");
+ _log.shout(error);
+ });
+
+ // Send the deep link.
+ await Adb.launchAppWithDeepLink(appPackage: appPackage, deepLink: deepLink);
+
+ // Wait until the deep link launches the app.
+ final isAppRunning = await Adb.waitForAppToLaunch(appPackage);
+ expect(
+ isAppRunning,
+ isTrue,
+ reason: "The app never launched after sending the deeplink. Package: $appPackage, Deeplink: $deepLink",
+ );
+
+ // Wait for a moment so that the app has time to start the Dart VM
+ // service and report it in the ADB logs.
+ //
+ // When running locally, waiting 1 second is probably sufficient. But
+ // when running in GitHub CI, we need to wait longer to make sure the
+ // Dart VM service reports its URL.
+ _log.info("Waiting a moment so that app can launch the Dart VM service.");
+ await Future.delayed(const Duration(seconds: 5));
+
+ // Ensure that we found the Dart VM service URL.
+ expect(
+ dartVmService,
+ isNotNull,
+ reason: "Couldn't find the Dart VM service for the app that was launched with a deep link.",
+ );
+ expect(
+ dartVmService,
+ isNotEmpty,
+ reason: "Couldn't find the Dart VM service for the app that was launched with a deep link.",
+ );
+
+ // Setup port forwarding between the host machine running the test, and the
+ // Android device that's running the app, so we can talk to the Dart VM service.
+ final port = Uri.parse(dartVmService!).port;
+ await Adb.forwardTcpPort(port);
+
+ // Connect to the Dart VM service in the app with Flutter Driver.
+ try {
+ driver = await FlutterDriver.connect(
+ dartVmServiceUrl: dartVmService,
+ );
+ } catch (exception) {
+ if (verbose) {
+ await _logVmDetailsAfterConnectionFailure(dartVmService!);
+ }
+
+ throw TestFailure(
+ "Couldn't connect FlutterDriver to the app's Dart VM service (the app successfully launched with the deep link, though)",
+ );
+ }
+
+ // Run the test.
+ await testRunner(driver);
+ });
+}
+
+Future _logVmDetailsAfterConnectionFailure(String dartVmService) async {
+ _log.warning("Failed to connect to the FlutterDriver!");
+
+ // Connect to the Dart VM service to query info.
+ late final VmService vmService;
+ try {
+ vmService = await vmServiceConnectUri(dartVmService);
+ } catch (exception) {
+ _log.warning("Tried to connect to the Dart VM service to provide more details, but we couldn't connect to it.");
+ _log.warning(exception);
+ return;
+ }
+
+ // Get the VM.
+ late final VM vm;
+ try {
+ vm = await vmService.getVM();
+ } catch (exception) {
+ _log.warning("Tried to get the VM from the Dart VM service, but we failed to query it.");
+ _log.warning(exception);
+ return;
+ }
+
+ _log.info('''
+Additional VM service info:
+ - name: ${vm.name}
+ - type: ${vm.type}
+ - host CPU: ${vm.hostCPU}
+ - target CPU: ${vm.targetCPU}
+ - OS: ${vm.operatingSystem}
+ - PID: ${vm.pid}
+''');
+
+ if (vm.isolates != null) {
+ _log.info("Isolates attached to the Dart VM service:");
+ for (final remoteIsolate in vm.isolates!) {
+ late final Isolate isolate;
+ try {
+ isolate = await vmService.getIsolate(remoteIsolate.id!);
+ } catch (exception) {
+ _log.warning("Tried to load isolate data for '${remoteIsolate.id}', but failed.");
+ continue;
+ }
+
+ _log.info('''Isolate:
+ - ID: ${isolate.id}
+ - name: ${isolate.name}
+ - type: ${isolate.type}
+ - is system isolate: ${isolate.isSystemIsolate}
+ - registered extensions:
+
+ ${isolate.extensionRPCs}
+''');
+ }
+ }
+}
+
+void _initLogs(bool writeLogs) {
+ if (!writeLogs) {
+ return;
+ }
+
+ Logger.root.level = Level.ALL;
+ Logger.root.onRecord.listen((record) {
+ // ignore: avoid_print
+ print('${record.level.name}: ${record.time}: ${record.message}');
+ });
+}
+
+final _log = Logger("flutter_test_runners.deep_links");
diff --git a/packages/flutter_test_runners/lib/src/deep_links/deep_links_ios.dart b/packages/flutter_test_runners/lib/src/deep_links/deep_links_ios.dart
new file mode 100644
index 0000000..385b0a8
--- /dev/null
+++ b/packages/flutter_test_runners/lib/src/deep_links/deep_links_ios.dart
@@ -0,0 +1,210 @@
+import 'package:flutter_driver/flutter_driver.dart';
+import 'package:flutter_test_runners/src/platform_comms/ios/xcrun.dart';
+import 'package:logging/logging.dart';
+import 'package:test/test.dart';
+import 'package:vm_service/vm_service.dart';
+import 'package:vm_service/vm_service_io.dart';
+
+/// A test that runs after launching the iOS app with the given
+/// [appBundleId], with the given [deepLink].
+///
+/// The test implementation is defined by the caller within [testRunner].
+/// The [testRunner] works the same way as a typical `test()` callback,
+/// except that the [testRunner] is given a [FlutterDriver] to inspect
+/// the app.
+///
+/// Tests that launch apps with deep links must use a [FlutterDriver],
+/// instead of a [WidgetTester], because [WidgetTester]s require building
+/// and launching the app with instrumentation. Launching an app with a
+/// deep link doesn't have instrumentation. Instead, the host machine
+/// users the [FlutterDriver] to talk to the running app.
+void testDeepLinkIosAppLaunch(
+ String description,
+ Future Function(FlutterDriver driver) testRunner, {
+ required String appBundleId,
+ required String deepLink,
+ bool verbose = false,
+ Duration timeout = const Duration(minutes: 5),
+}) {
+ test(description, () async {
+ _initLogs(verbose);
+ _log.info("Running deep link test driver...");
+
+ // // Pre-emptively the kill the app, in case it's already running.
+ // _log.info("Pre-emptively killing the app");
+ // await Xcrun.killApp(appBundleId);
+
+ FlutterDriver? driver;
+ // addTearDown(() async {
+ // _log.info("Cleaning up after the test");
+ // // Dispose the FlutterDriver connection.
+ // driver?.serviceClient.dispose();
+ //
+ // // Kill the app when we're done.
+ // await Xcrun.killApp(appBundleId);
+ // });
+
+ // Ensure the app isn't running yet.
+ _log.info("Checking if the app is running...");
+ expect(await Xcrun.isAppRunning(appBundleId), isFalse);
+ _log.info("We've verified the app isn't running");
+
+ // FIXME: At the moment GitHub CI is saying this operation isn't permitted.
+ // // Clear previous logcat messages so we don't try to connect to a previous
+ // // Dart VM service listing.
+ // _log.info("Clearing old logs");
+ // await Xcrun.clearLogs();
+ // _log.info("We've cleared old logs");
+ print("NOT clearing logs because GitHub CI says not permitted");
+
+ // Listen to iOS logs to find the Dart VM service for the running app.
+ _log.info("Registering for simulator logs");
+ String? dartVmService;
+ await Xcrun.listenToXcrunForFlutterLogs(
+ appBundleId,
+ onLog: (log) {
+ // _log.info(log);
+ if (log.contains("Dart VM service")) {
+ _log.info("Found Dart VM log:\n$log");
+
+ final regex = RegExp(r'.*Dart VM service.*(http[s]?://[^\s]+)');
+ final httpUrl = Uri.parse(regex.firstMatch(log)!.group(1)!);
+
+ dartVmService =
+ Uri(scheme: "ws", host: httpUrl.host, port: httpUrl.port, path: "${httpUrl.path}ws").toString();
+ }
+ },
+ onError: (error) {
+ _log.shout("iOS ERROR:");
+ _log.shout(error);
+ },
+ );
+ _log.info("We're now listening to logs and errors from iOS");
+
+ // Send the deep link.
+ _log.info("Sending the deep link: $deepLink");
+ await Xcrun.launchAppWithUniversalLink(universalLink: deepLink);
+
+ // Wait until the deep link launches the app.
+ _log.info("Waiting for app to launch: $appBundleId");
+ final isAppRunning = await Xcrun.waitForAppToLaunch(appBundleId);
+ expect(
+ isAppRunning,
+ isTrue,
+ reason: "The app never launched after sending the deeplink. Package: $appBundleId, Deeplink: $deepLink",
+ );
+
+ // // Wait for a moment so that the app has time to start the Dart VM
+ // // service and report it in the device logs.
+ // _log.info("Waiting a moment so that app can launch the Dart VM service.");
+ // await Future.delayed(const Duration(seconds: 5));
+ //
+ // // Ensure that we found the Dart VM service URL.
+ // expect(
+ // dartVmService,
+ // isNotNull,
+ // reason: "Couldn't find the Dart VM service for the app that was launched with a deep link.",
+ // );
+ // expect(
+ // dartVmService,
+ // isNotEmpty,
+ // reason: "Couldn't find the Dart VM service for the app that was launched with a deep link.",
+ // );
+ //
+ // // Setup port forwarding between the host machine running the test, and the
+ // // Android device that's running the app, so we can talk to the Dart VM service.
+ // final port = Uri.parse(dartVmService!).port;
+ // _log.info("Forwarding simulator port: $port");
+ // await Xcrun.forwardTcpPort(port);
+ //
+ // // Connect to the Dart VM service in the app with Flutter Driver.
+ // try {
+ // _log.info("Connecting to Flutter Driver extension in the Dart VM service.");
+ // driver = await FlutterDriver.connect(
+ // dartVmServiceUrl: dartVmService,
+ // );
+ // } catch (exception) {
+ // if (verbose) {
+ // await _logVmDetailsAfterConnectionFailure(dartVmService!);
+ // }
+ //
+ // throw TestFailure(
+ // "Couldn't connect FlutterDriver to the app's Dart VM service (the app successfully launched with the deep link, though)",
+ // );
+ // }
+ //
+ // // Run the test.
+ // await testRunner(driver);
+ }, timeout: Timeout(timeout));
+}
+
+Future _logVmDetailsAfterConnectionFailure(String dartVmService) async {
+ _log.warning("Failed to connect to the FlutterDriver!");
+
+ // Connect to the Dart VM service to query info.
+ late final VmService vmService;
+ try {
+ vmService = await vmServiceConnectUri(dartVmService);
+ } catch (exception) {
+ _log.warning("Tried to connect to the Dart VM service to provide more details, but we couldn't connect to it.");
+ _log.warning(exception);
+ return;
+ }
+
+ // Get the VM.
+ late final VM vm;
+ try {
+ vm = await vmService.getVM();
+ } catch (exception) {
+ _log.warning("Tried to get the VM from the Dart VM service, but we failed to query it.");
+ _log.warning(exception);
+ return;
+ }
+
+ _log.info('''
+Additional VM service info:
+ - name: ${vm.name}
+ - type: ${vm.type}
+ - host CPU: ${vm.hostCPU}
+ - target CPU: ${vm.targetCPU}
+ - OS: ${vm.operatingSystem}
+ - PID: ${vm.pid}
+''');
+
+ if (vm.isolates != null) {
+ _log.info("Isolates attached to the Dart VM service:");
+ for (final remoteIsolate in vm.isolates!) {
+ late final Isolate isolate;
+ try {
+ isolate = await vmService.getIsolate(remoteIsolate.id!);
+ } catch (exception) {
+ _log.warning("Tried to load isolate data for '${remoteIsolate.id}', but failed.");
+ continue;
+ }
+
+ _log.info('''Isolate:
+ - ID: ${isolate.id}
+ - name: ${isolate.name}
+ - type: ${isolate.type}
+ - is system isolate: ${isolate.isSystemIsolate}
+ - registered extensions:
+
+ ${isolate.extensionRPCs}
+''');
+ }
+ }
+}
+
+void _initLogs(bool writeLogs) {
+ if (!writeLogs) {
+ return;
+ }
+
+ Logger.root.level = Level.ALL;
+ Logger.root.onRecord.listen((record) {
+ // ignore: avoid_print
+ print('${record.level.name}: ${record.time}: ${record.message}');
+ });
+}
+
+final _log = Logger("flutter_test_runners.deep_links");
diff --git a/packages/flutter_test_runners/lib/src/platform_comms/android/adb.dart b/packages/flutter_test_runners/lib/src/platform_comms/android/adb.dart
new file mode 100644
index 0000000..1da93a0
--- /dev/null
+++ b/packages/flutter_test_runners/lib/src/platform_comms/android/adb.dart
@@ -0,0 +1,108 @@
+import 'dart:convert';
+import 'dart:io';
+
+/// A Dart interface for common Android Debug Bridge (ADB) commands.
+class Adb {
+ /// Returns `true` if the app with the given [appPackage] ID is currently
+ /// in memory on the Android device.
+ ///
+ /// A return value of `true` doesn't mean the app is visible. The app might
+ /// be in the background, but still in memory.
+ static Future isAppRunning(String appPackage) async {
+ final result = await Process.run(
+ "sh",
+ ["-c", "adb shell ps | grep $appPackage"],
+ );
+ final output = result.stdout;
+ return output != null && output is String && output.isNotEmpty;
+ }
+
+ /// Starts listening to ADB logcat for Android logs, and returns the
+ /// [Process] that's listening to logcat.
+ ///
+ /// This method assumes that `stdout` and `stderr` from Logcat send messages
+ /// with UTF8 encoding. If anything else is received, the behavior is undefined,
+ /// but probably an error.
+ static Future listenToAdbForFlutterLogs({
+ void Function(String)? onLog,
+ void Function(String)? onError,
+ }) async {
+ final result = await Process.start("adb", ["logcat", "-s", "flutter"]);
+
+ result.stdout.transform(utf8.decoder).listen(onLog);
+ result.stderr.transform(utf8.decoder).listen(onError);
+
+ return result;
+ }
+
+ /// Connects the given TCP [port] from the host machine to the running Android
+ /// device.
+ ///
+ /// This is useful, for example, when you want to connect to the Dart VM service
+ /// running in a debug Flutter app on an Android device.
+ static Future forwardTcpPort(int port) async {
+ await Process.run("adb", ["forward", "tcp:$port", "tcp:$port"]);
+ }
+
+ /// Tells Android to launch the app with the given [appPackage] ID using
+ /// the given [deepLink].
+ ///
+ /// The structure of the deep link is determined by the given app.
+ static Future launchAppWithDeepLink({
+ required String appPackage,
+ required String deepLink,
+ }) async {
+ await Process.start("adb", [
+ "shell",
+ "am",
+ "start",
+ "-W",
+ "-a",
+ "android.intent.action.VIEW",
+ "-d",
+ "\"$deepLink\"",
+ appPackage,
+ ]);
+ }
+
+ /// Waits for the app with the given [appPackage] to appear in memory.
+ ///
+ /// This method polls the OS to check if the app is running. To use a custom
+ /// polling duration, provide a [pollDuration].
+ ///
+ /// This method fails if the app hasn't launched within the given [timeout]
+ /// duration.
+ static Future waitForAppToLaunch(
+ String appPackage, {
+ Duration pollDuration = const Duration(milliseconds: 250),
+ Duration timeout = const Duration(seconds: 10),
+ }) async {
+ final now = DateTime.now();
+
+ bool isAppRunning = false;
+ do {
+ isAppRunning = await Adb.isAppRunning(appPackage);
+ if (!isAppRunning) {
+ await Future.delayed(pollDuration);
+ }
+ } while (!isAppRunning && (DateTime.now().difference(now) < timeout));
+
+ return isAppRunning;
+ }
+
+ /// Kills the app with the given [package] ID, e.g., com.acme.myapp.
+ static Future killApp(String package) async {
+ await Process.run("adb", ["shell", "am", "force-stop", package]);
+ }
+
+ /// Clears all logs in logcat.
+ ///
+ /// Note: Logcat retains logs such that connecting to logcat will
+ /// initially print a bunch of old logs before printing new logs.
+ /// When searching logs for specific info, like a URL, those old logs
+ /// can lead to an attempt to connect to dead services. This method
+ /// clears those logs before listening for new logs.
+ static Future clearLogcat() async {
+ await Process.run("adb", ["logcat", "-b", "all", "-c"]);
+ }
+}
diff --git a/packages/flutter_test_runners/lib/src/platform_comms/ios/xcrun.dart b/packages/flutter_test_runners/lib/src/platform_comms/ios/xcrun.dart
new file mode 100644
index 0000000..7542f21
--- /dev/null
+++ b/packages/flutter_test_runners/lib/src/platform_comms/ios/xcrun.dart
@@ -0,0 +1,219 @@
+import 'dart:convert';
+import 'dart:io';
+
+import 'package:flutter_test/flutter_test.dart';
+
+/// A Dart interface for common `xcrun` commands.
+class Xcrun {
+ /// Returns `true` if the app with the given [appBundleId] ID is currently
+ /// in memory on the iOS device.
+ ///
+ /// A return value of `true` doesn't mean the app is visible. The app might
+ /// be in the background, but still in memory.
+ static Future isAppRunning(String appBundleId) async {
+ print("isAppRunning() - $appBundleId");
+ // final result = await Process.run(
+ // "sh",
+ // [
+ // "-c",
+ // "xcrun simctl spawn booted launchctl list | grep \"$appBundleId\"",
+ // ],
+ // runInShell: true,
+ // );
+
+ // final result = await Process.run("sh", [
+ // "-c",
+ // "xcrun simctl spawn booted launchctl list | grep \"$appBundleId\"",
+ // ]);
+
+ print("Trying command through shell - no grep...");
+ var result = await _runInShell([
+ "xcrun simctl spawn booted launchctl list",
+ ]);
+ print("Done with command without grep:");
+ // print(result.stdout);
+ final output = result.stdout;
+ if (output is! String) {
+ // We don't know how to handle this.
+ print("Received shell output that isn't a String. Don't know what to do with this.");
+ return false;
+ }
+
+ final isAppRunning = output.contains(appBundleId);
+ print("Is app running? $isAppRunning - searched ${output.split("\n").length} running processes");
+ return isAppRunning;
+
+ // print("Trying command through shell with '| grep'...");
+ // result = await _runInShell([
+ // "xcrun simctl spawn booted launchctl list | grep \"$appBundleId\"",
+ // ]);
+ // final output = result.stdout;
+ // print("Is app running? ${output != null && output is String && output.isNotEmpty}");
+ // return output != null && output is String && output.isNotEmpty;
+ }
+
+ /// Starts listening to the running iOS device's log stream, and returns the
+ /// [Process] that's listening.
+ ///
+ /// This method assumes that `stdout` and `stderr` from Logcat send messages
+ /// with UTF8 encoding. If anything else is received, the behavior is undefined,
+ /// but probably an error.
+ static Future listenToXcrunForFlutterLogs(
+ String appBundleId, {
+ void Function(String)? onLog,
+ void Function(String)? onError,
+ }) async {
+ // This command doesn't work when run with a "sh -c". It also doesn't
+ // work when concatenating the args into a single string.
+ final result = await Process.start(
+ "xcrun",
+ [
+ "simctl",
+ "spawn",
+ "booted",
+ "log",
+ "stream",
+ "--level",
+ "debug",
+ // Only log things related to the desired app.
+ "--predicate",
+ "(eventMessage CONTAINS '$appBundleId' OR eventMessage CONTAINS 'flutter')",
+ ],
+ runInShell: true,
+ );
+
+ result.stdout.transform(utf8.decoder).listen(onLog);
+ result.stderr.transform(utf8.decoder).listen(onError);
+
+ return result;
+ }
+
+ /// Connects the given TCP [port] from the host machine to the running iOS
+ /// device.
+ ///
+ /// This is useful, for example, when you want to connect to the Dart VM service
+ /// running in a debug Flutter app on an iOS device.
+ static Future forwardTcpPort(int port) {
+ return _runInShell(["xcrun", "simctl", "port", "forward", "booted", "$port:$port"]);
+ }
+
+ /// Tells iOS to launch the given Universal Link, which might launch an app, if
+ /// an app is registered to handle the domain of the link.
+ ///
+ /// The structure of the deep link is determined by the given app.
+ static Future launchAppWithUniversalLink({
+ required String universalLink,
+ }) {
+ // Note: This command only works when run with "sh" and the
+ // command as a single string. If the command is passed as
+ // individual arguments, it doesn't work. If the command is
+ // run without "sh" and `runInShell` is `true`, it won't work.
+ return _runInShell(["sudo xcrun simctl openurl booted \"$universalLink\""]);
+ // return Process.run(
+ // "sh",
+ // ["-c", "xcrun simctl openurl booted \"$universalLink\""],
+ // );
+ }
+
+ /// Waits for the app with the given [appBundleId] to appear in memory.
+ ///
+ /// This method polls the OS to check if the app is running. To use a custom
+ /// polling duration, provide a [pollDuration].
+ ///
+ /// This method fails if the app hasn't launched within the given [timeout]
+ /// duration.
+ static Future waitForAppToLaunch(
+ String appBundleId, {
+ Duration pollDuration = const Duration(milliseconds: 250),
+ Duration timeout = const Duration(seconds: 10),
+ }) async {
+ final now = DateTime.now();
+
+ bool isAppRunning = false;
+ do {
+ isAppRunning = await Xcrun.isAppRunning(appBundleId);
+ if (!isAppRunning) {
+ await Future.delayed(pollDuration);
+ }
+ } while (!isAppRunning && (DateTime.now().difference(now) < timeout));
+
+ return isAppRunning;
+ }
+
+ /// Kills the app with the given [appBundleId] ID, e.g., `com.acme.myapp`.
+ static Future killApp(String appBundleId) async {
+ // final result = await Process.run(
+ // "xcrun",
+ // ["simctl", "terminate", "booted", appBundleId],
+ // runInShell: true,
+ // );
+
+ print("Sending xcrun simctl terminate command...");
+ final process = await Process.start(
+ "sh",
+ ["-c", "xcrun simctl terminate booted $appBundleId"],
+ );
+ print("terminate command process was started");
+
+ process.stdin.close();
+
+ stdout.addStream(process.stdout);
+ stderr.addStream(process.stderr);
+
+ // process.stdout.transform(utf8.decoder).listen((log) {
+ // print("terminate command log: $log");
+ // });
+ //
+ // process.stderr.transform(utf8.decoder).listen((error) {
+ // print("terminate command error: $error");
+ // });
+
+ print("Waiting for exit code...");
+ final exitCode = await process.exitCode;
+ print("Killed app - exit code: $exitCode");
+ }
+
+ /// Clears all logs in the iOS log stream.
+ static Future clearLogs() async {
+ await _runInShell(["xcrun", "simctl", "spawn", "booted", "log", "erase"]);
+ }
+
+ static Future _startInShell(List commandAndArgs) {
+ return Process.start("sh", ["-c", ...commandAndArgs]);
+
+ // return Process.start(
+ // commandAndArgs.first,
+ // commandAndArgs.length > 1 ? commandAndArgs.sublist(1) : [],
+ // runInShell: true,
+ // );
+ }
+
+ static Future _runInShell(List commandAndArgs) async {
+ final command = commandAndArgs.join(" ");
+ print("Sending shell command: '$command'");
+ final result = await Process.run("sh", ["--verbose", "--debug", "-c", command]);
+ print("Shell command exit code: ${result.exitCode}");
+
+ if (result.exitCode != 0) {
+ throw Exception('''
+Failed to execute command in a shell:
+'$command'
+
+Exit code: ${result.exitCode}
+
+Stdout:
+${result.stdout}
+
+Stderr:
+${result.stderr}''');
+ }
+
+ return result;
+
+ // return Process.run(
+ // commandAndArgs.first,
+ // commandAndArgs.length > 1 ? commandAndArgs.sublist(1) : [],
+ // runInShell: true,
+ // );
+ }
+}
diff --git a/packages/flutter_test_runners/pubspec.yaml b/packages/flutter_test_runners/pubspec.yaml
index ede39a4..4824344 100644
--- a/packages/flutter_test_runners/pubspec.yaml
+++ b/packages/flutter_test_runners/pubspec.yaml
@@ -12,7 +12,14 @@ dependencies:
sdk: flutter
flutter_test:
sdk: flutter
+ flutter_driver:
+ sdk: flutter
+
meta: ^1.9.1
+ test: any
+ vm_service: any
+ logging: ^1.3.0
+
dev_dependencies:
flutter_lints: ^2.0.0
diff --git a/pubspec.lock b/pubspec.lock
index 949529f..5c7e4d3 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -1,6 +1,22 @@
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
+ _fe_analyzer_shared:
+ dependency: transitive
+ description:
+ name: _fe_analyzer_shared
+ sha256: "0b2f2bd91ba804e53a61d757b986f89f1f9eaed5b11e4b2f5a2468d86d6c9fc7"
+ url: "https://pub.dev"
+ source: hosted
+ version: "67.0.0"
+ analyzer:
+ dependency: transitive
+ description:
+ name: analyzer
+ sha256: "37577842a27e4338429a1cbc32679d508836510b056f1eedf0c8d20e39c1383d"
+ url: "https://pub.dev"
+ source: hosted
+ version: "6.4.1"
ansi_styles:
dependency: transitive
description:
@@ -73,6 +89,30 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.6.0+1"
+ convert:
+ dependency: transitive
+ description:
+ name: convert
+ sha256: b30acd5944035672bc15c6b7a8b47d773e41e2f17de064350988c5d02adb1c68
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.1.2"
+ coverage:
+ dependency: transitive
+ description:
+ name: coverage
+ sha256: e3493833ea012784c740e341952298f1cc77f1f01b1bbc3eb4eecf6984fb7f43
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.11.1"
+ crypto:
+ dependency: transitive
+ description:
+ name: crypto
+ sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.0.6"
file:
dependency: transitive
description:
@@ -81,6 +121,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "6.1.4"
+ frontend_server_client:
+ dependency: transitive
+ description:
+ name: frontend_server_client
+ sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694
+ url: "https://pub.dev"
+ source: hosted
+ version: "4.0.0"
glob:
dependency: transitive
description:
@@ -105,6 +153,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.1.0"
+ http_multi_server:
+ dependency: transitive
+ description:
+ name: http_multi_server
+ sha256: aa6199f908078bb1c5efb8d8638d4ae191aac11b311132c3ef48ce352fb52ef8
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.2.2"
http_parser:
dependency: transitive
description:
@@ -121,6 +177,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.0.4"
+ js:
+ dependency: transitive
+ description:
+ name: js
+ sha256: c1b2e9b5ea78c45e1a0788d29606ba27dc5f71f019f32ca5140f61ef071838cf
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.7.1"
json_annotation:
dependency: transitive
description:
@@ -129,14 +193,22 @@ packages:
url: "https://pub.dev"
source: hosted
version: "4.8.1"
+ logging:
+ dependency: transitive
+ description:
+ name: logging
+ sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.3.0"
matcher:
dependency: transitive
description:
name: matcher
- sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e"
+ sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2
url: "https://pub.dev"
source: hosted
- version: "0.12.16"
+ version: "0.12.17"
melos:
dependency: "direct main"
description:
@@ -149,10 +221,18 @@ packages:
dependency: transitive
description:
name: meta
- sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3"
+ sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.16.0"
+ mime:
+ dependency: transitive
+ description:
+ name: mime
+ sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6"
url: "https://pub.dev"
source: hosted
- version: "1.9.1"
+ version: "2.0.0"
mustache_template:
dependency: transitive
description:
@@ -161,6 +241,22 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.0.0"
+ node_preamble:
+ dependency: transitive
+ description:
+ name: node_preamble
+ sha256: "6e7eac89047ab8a8d26cf16127b5ed26de65209847630400f9aefd7cd5c730db"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.0.2"
+ package_config:
+ dependency: transitive
+ description:
+ name: package_config
+ sha256: "92d4488434b520a62570293fbd33bb556c7d49230791c1b4bbd973baf6d2dc67"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.1.1"
path:
dependency: transitive
description:
@@ -233,6 +329,54 @@ packages:
url: "https://pub.dev"
source: hosted
version: "3.2.1"
+ shelf:
+ dependency: transitive
+ description:
+ name: shelf
+ sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.4.1"
+ shelf_packages_handler:
+ dependency: transitive
+ description:
+ name: shelf_packages_handler
+ sha256: "89f967eca29607c933ba9571d838be31d67f53f6e4ee15147d5dc2934fee1b1e"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.0.2"
+ shelf_static:
+ dependency: transitive
+ description:
+ name: shelf_static
+ sha256: c87c3875f91262785dade62d135760c2c69cb217ac759485334c5857ad89f6e3
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.1.3"
+ shelf_web_socket:
+ dependency: transitive
+ description:
+ name: shelf_web_socket
+ sha256: cc36c297b52866d203dbf9332263c94becc2fe0ceaa9681d07b6ef9807023b67
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.0.1"
+ source_map_stack_trace:
+ dependency: transitive
+ description:
+ name: source_map_stack_trace
+ sha256: c0713a43e323c3302c2abe2a1cc89aa057a387101ebd280371d6a6c9fa68516b
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.1.2"
+ source_maps:
+ dependency: transitive
+ description:
+ name: source_maps
+ sha256: "190222579a448b03896e0ca6eca5998fa810fda630c1d65e2f78b3f638f54812"
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.10.13"
source_span:
dependency: transitive
description:
@@ -273,14 +417,30 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.2.1"
+ test:
+ dependency: "direct main"
+ description:
+ name: test
+ sha256: "8391fbe68d520daf2314121764d38e37f934c02fd7301ad18307bd93bd6b725d"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.25.14"
test_api:
dependency: transitive
description:
name: test_api
- sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b"
+ sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd
url: "https://pub.dev"
source: hosted
- version: "0.6.1"
+ version: "0.7.4"
+ test_core:
+ dependency: transitive
+ description:
+ name: test_core
+ sha256: "84d17c3486c8dfdbe5e12a50c8ae176d15e2a771b96909a9442b40173649ccaa"
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.6.8"
typed_data:
dependency: transitive
description:
@@ -297,6 +457,54 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.0.0"
+ vm_service:
+ dependency: "direct main"
+ description:
+ name: vm_service
+ sha256: ddfa8d30d89985b96407efce8acbdd124701f96741f2d981ca860662f1c0dc02
+ url: "https://pub.dev"
+ source: hosted
+ version: "15.0.0"
+ watcher:
+ dependency: transitive
+ description:
+ name: watcher
+ sha256: "69da27e49efa56a15f8afe8f4438c4ec02eff0a117df1b22ea4aad194fe1c104"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.1.1"
+ web:
+ dependency: transitive
+ description:
+ name: web
+ sha256: cd3543bd5798f6ad290ea73d210f423502e71900302dde696f8bff84bf89a1cb
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.1.0"
+ web_socket:
+ dependency: transitive
+ description:
+ name: web_socket
+ sha256: "3c12d96c0c9a4eec095246debcea7b86c0324f22df69893d538fcc6f1b8cce83"
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.1.6"
+ web_socket_channel:
+ dependency: transitive
+ description:
+ name: web_socket_channel
+ sha256: "9f187088ed104edd8662ca07af4b124465893caf063ba29758f97af57e61da8f"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.0.1"
+ webkit_inspection_protocol:
+ dependency: transitive
+ description:
+ name: webkit_inspection_protocol
+ sha256: "87d3f2333bb240704cd3f1c6b5b7acd8a10e7f0bc28c28dcf14e782014f4a572"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.2.1"
yaml:
dependency: transitive
description:
@@ -314,4 +522,4 @@ packages:
source: hosted
version: "2.1.1"
sdks:
- dart: ">=3.2.0-122.0.dev <4.0.0"
+ dart: ">=3.5.0 <4.0.0"
diff --git a/pubspec.yaml b/pubspec.yaml
index 3c523ae..9254500 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -5,4 +5,3 @@ environment:
dependencies:
melos: ^3.1.1
-