-
Notifications
You must be signed in to change notification settings - Fork 4
Add android e2e setup + simulator run iOS e2e #546
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
16 commits
Select commit
Hold shift + click to select a range
ba5a960
feat: initial setup patrol e2e
dewabisma f9c92dc
feat: add create account e2e test
dewabisma c618ef2
feat: add import wallet, update real iphone device e2e script
dewabisma daf0be9
chore: add log for error register notification
dewabisma 1ad9bdf
feat: uncommit generated and sensitive files
dewabisma 0de8697
feat: add error to telemetry
dewabisma 74c67f4
fix: DRY best effort registering remote notification
dewabisma 3b1b01b
chore: formatting
dewabisma 1986d6f
feat: setup android e2e test
dewabisma 8ff666b
feat: add simulator test script
dewabisma 7c38e21
Merge branch 'main' of https://github.com/Quantus-Network/quantus-app…
dewabisma 2456ccf
fix: refactor scripts DRY
dewabisma 794715f
fix: inconsistent boot simulator behavior
dewabisma 4c0f52b
fix: not waiting for booting
dewabisma ebdc0c2
fix: not consuming args
dewabisma 2e563c2
fix: device name parsing
dewabisma File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
41 changes: 41 additions & 0 deletions
41
mobile-app/android/app/src/androidTest/java/com/quantus/wallet/MainActivityTest.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| package com.quantus.wallet; | ||
|
|
||
| import androidx.test.platform.app.InstrumentationRegistry; | ||
|
|
||
| import com.example.resonance_network_wallet.MainActivity; | ||
|
|
||
| import org.junit.Test; | ||
| import org.junit.runner.RunWith; | ||
| import org.junit.runners.Parameterized; | ||
| import org.junit.runners.Parameterized.Parameters; | ||
|
|
||
| import pl.leancode.patrol.PatrolJUnitRunner; | ||
|
|
||
| // This is the entry point that lets Patrol drive the Flutter integration tests | ||
| // under patrol_test/ as native Android instrumentation tests. Each Dart test is | ||
| // surfaced as a parameterized JUnit test case so it can be run/filtered | ||
| // individually by xcodebuild's Android equivalent (the orchestrator). | ||
| @RunWith(Parameterized.class) | ||
| public class MainActivityTest { | ||
| @Parameters(name = "{0}") | ||
| public static Object[] testCases() { | ||
| PatrolJUnitRunner instrumentation = | ||
| (PatrolJUnitRunner) InstrumentationRegistry.getInstrumentation(); | ||
| instrumentation.setUp(MainActivity.class); | ||
| instrumentation.waitForPatrolAppService(); | ||
| return instrumentation.listDartTests(); | ||
| } | ||
|
|
||
| public MainActivityTest(String dartTestName) { | ||
| this.dartTestName = dartTestName; | ||
| } | ||
|
|
||
| private final String dartTestName; | ||
|
|
||
| @Test | ||
| public void runDartTest() { | ||
| PatrolJUnitRunner instrumentation = | ||
| (PatrolJUnitRunner) InstrumentationRegistry.getInstrumentation(); | ||
| instrumentation.runDartTest(dartTestName); | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,105 @@ | ||
| # Shared helpers for Patrol E2E runner scripts under mobile-app/scripts/. | ||
| # Source from a script in that directory, e.g.: | ||
| # source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/lib/patrol_common.sh" | ||
|
|
||
| # Resolve SCRIPT_DIR / APP_ROOT from the calling script and cd to APP_ROOT. | ||
| patrol_resolve_app_root() { | ||
| local caller_source="${1:?patrol_resolve_app_root requires the caller script path}" | ||
| SCRIPT_DIR="$(cd "$(dirname "$caller_source")" && pwd)" | ||
| APP_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" | ||
| cd "$APP_ROOT" | ||
| } | ||
|
|
||
| # Default BUILD_MODE and TEST_TARGETS before parsing CLI args. | ||
| patrol_init_runner_args() { | ||
| BUILD_MODE="--debug" | ||
| TEST_TARGETS=() | ||
| } | ||
|
|
||
| # Parse shared Patrol runner flags. Platform-specific options are delegated to | ||
| # the optional callback, which must set PLATFORM_CONSUMED to the number of args | ||
| # consumed and return 0 when it handles a flag (return 1 when unrecognized). | ||
| # | ||
| # Usage: | ||
| # patrol_parse_runner_args <usage_fn> <supports_build_mode:true|false> \ | ||
| # [<platform_option_fn>] "$@" | ||
| patrol_parse_runner_args() { | ||
| local usage_fn="$1" | ||
| local supports_build_mode="$2" | ||
| local platform_option_fn="${3:--}" | ||
| shift 3 | ||
|
|
||
| patrol_init_runner_args | ||
|
|
||
| while [[ $# -gt 0 ]]; do | ||
| PLATFORM_CONSUMED=0 | ||
| if [[ "$platform_option_fn" != "-" ]] && "$platform_option_fn" "$@"; then | ||
| shift "$PLATFORM_CONSUMED" | ||
| continue | ||
| fi | ||
|
|
||
| case "$1" in | ||
| --debug|--release) | ||
| if [[ "$supports_build_mode" != "true" ]]; then | ||
| echo "ERROR: unknown option: $1" >&2 | ||
| "$usage_fn" | ||
| exit 1 | ||
| fi | ||
| BUILD_MODE="$1" | ||
| shift | ||
| ;; | ||
| -h|--help) | ||
| "$usage_fn" | ||
| exit 0 | ||
| ;; | ||
| --) | ||
| shift | ||
| TEST_TARGETS+=("$@") | ||
| break | ||
| ;; | ||
| -*) | ||
| echo "ERROR: unknown option: $1" >&2 | ||
| "$usage_fn" | ||
| exit 1 | ||
| ;; | ||
| *) | ||
| TEST_TARGETS+=("$1") | ||
| shift | ||
| ;; | ||
| esac | ||
| done | ||
| } | ||
|
|
||
| # Test secrets/fixtures (e.g. TEST_IMPORT_MNEMONIC) are injected at build time via | ||
| # --dart-define so they are never bundled into the app as an asset. | ||
| # * Locally: read from a gitignored .env.test (key=value) via --dart-define-from-file. | ||
| # * CI: export TEST_IMPORT_MNEMONIC (and any others) from the runner's secret store. | ||
| patrol_collect_dart_defines() { | ||
| DART_DEFINES=() | ||
| if [[ -f .env.test ]]; then | ||
| echo "==> Injecting test secrets from .env.test" | ||
| DART_DEFINES+=(--dart-define-from-file=.env.test) | ||
| elif [[ -n "${TEST_IMPORT_MNEMONIC:-}" ]]; then | ||
| echo "==> Injecting test secrets from environment" | ||
| DART_DEFINES+=(--dart-define=TEST_IMPORT_MNEMONIC="$TEST_IMPORT_MNEMONIC") | ||
| else | ||
| echo "WARNING: no .env.test file and TEST_IMPORT_MNEMONIC is unset;" \ | ||
| "tests that need a seed phrase (e.g. import_wallet) will fail." >&2 | ||
| fi | ||
| } | ||
|
|
||
| # Build the `-t <target>` flags from TEST_TARGETS. With no targets, patrol bundles | ||
| # every `*_test.dart` under `patrol_test/`, i.e. the whole suite in one binary. | ||
| # Optional first argument is the verb in the "no targets" message (default: running). | ||
| patrol_build_target_args() { | ||
| local action="${1:-running}" | ||
| TARGET_ARGS=() | ||
| if [[ ${#TEST_TARGETS[@]} -gt 0 ]]; then | ||
| for target in "${TEST_TARGETS[@]}"; do | ||
| TARGET_ARGS+=(-t "$target") | ||
| done | ||
| echo "==> Test targets: ${TEST_TARGETS[*]}" | ||
| else | ||
| echo "==> No targets given; ${action} the WHOLE patrol_test suite." | ||
| fi | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,173 @@ | ||
| #!/usr/bin/env bash | ||
| # | ||
| # Run Patrol E2E tests on an Android emulator. | ||
| # | ||
| # Android counterpart of scripts/patrol_ios_device.sh, scoped to emulators for | ||
| # local E2E runs. Unlike iOS physical devices, `patrol test` can build and run | ||
| # in one step on Android without the xcodebuild destination-timeout workaround. | ||
| # | ||
| # Usage: | ||
| # scripts/patrol_android_emulator.sh [options] [test_target ...] | ||
| # | ||
| # Options: | ||
| # -d, --device <serial> Emulator serial (default: first running emulator). | ||
| # -a, --avd <name> Start this AVD when no emulator is running. | ||
| # --debug Build a debug binary (default). | ||
| # --release Build a release binary. | ||
| # | ||
| # Environment: | ||
| # ANDROID_EMULATOR_AVD Default AVD to boot when none is running and -a | ||
| # is not passed (falls back to the first listed AVD). | ||
| # EMULATOR_BOOT_TIMEOUT Seconds to wait for boot (default: 120). | ||
| # | ||
| # Test targets: | ||
| # * Pass zero targets to run the WHOLE suite: patrol bundles every | ||
| # `*_test.dart` under `patrol_test/` into a single app binary. | ||
| # * Pass one or more targets to run only those files. | ||
| # | ||
| # Examples: | ||
| # # Run all e2e tests on the first running emulator: | ||
| # scripts/patrol_android_emulator.sh | ||
| # | ||
| # # Boot a specific AVD, then run tests: | ||
| # scripts/patrol_android_emulator.sh -a Pixel_8_API_35 | ||
| # | ||
| # # Run a single test: | ||
| # scripts/patrol_android_emulator.sh patrol_test/smoke/hello_world_test.dart | ||
| # | ||
| # Notes: | ||
| # * Start an emulator in Android Studio, or pass -a / set ANDROID_EMULATOR_AVD. | ||
| # * Run from anywhere; paths are resolved relative to this script. | ||
|
|
||
| # Note: intentionally not using `pipefail`. A step pipes into `head`, which | ||
| # closes the pipe early and would otherwise raise SIGPIPE (exit 141) and abort | ||
| # the whole script under `set -e`. | ||
| set -eu | ||
|
|
||
| # shellcheck source=lib/patrol_common.sh | ||
| source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/lib/patrol_common.sh" | ||
|
|
||
| usage() { | ||
| echo "Usage: patrol_android_emulator.sh [-d <serial>] [-a <avd>] [--debug|--release] [test_target ...]" >&2 | ||
| } | ||
|
|
||
| patrol_android_emulator_platform_option() { | ||
| case "$1" in | ||
| -d|--device) | ||
| DEVICE_SERIAL="${2:?--device requires a serial}" | ||
| PLATFORM_CONSUMED=2 | ||
| return 0 | ||
| ;; | ||
| -a|--avd) | ||
| AVD_NAME="${2:?--avd requires a name}" | ||
| PLATFORM_CONSUMED=2 | ||
| return 0 | ||
| ;; | ||
| esac | ||
| return 1 | ||
| } | ||
|
|
||
| first_running_emulator() { | ||
| adb devices 2>/dev/null | awk '$2 == "device" && $1 ~ /^emulator-/ {print $1; exit}' | ||
| } | ||
|
|
||
| first_listed_avd() { | ||
| if ! command -v emulator >/dev/null 2>&1; then | ||
| return 1 | ||
| fi | ||
| emulator -list-avds 2>/dev/null | head -1 | ||
| } | ||
|
|
||
| wait_for_emulator_boot() { | ||
| local serial="$1" | ||
| local timeout="${EMULATOR_BOOT_TIMEOUT:-120}" | ||
| echo "==> Waiting for $serial to finish booting (timeout ${timeout}s)..." | ||
| adb -s "$serial" wait-for-device | ||
| local start | ||
| start="$(date +%s)" | ||
| while true; do | ||
| local boot_completed | ||
| boot_completed="$(adb -s "$serial" shell getprop sys.boot_completed 2>/dev/null | tr -d '\r')" | ||
| if [[ "$boot_completed" == "1" ]]; then | ||
| echo "==> Emulator ready: $serial" | ||
| return 0 | ||
| fi | ||
| if (( $(date +%s) - start > timeout )); then | ||
| echo "ERROR: Emulator $serial did not boot within ${timeout}s." >&2 | ||
| exit 1 | ||
| fi | ||
| sleep 2 | ||
| done | ||
| } | ||
|
|
||
| start_emulator() { | ||
| local avd_name="$1" | ||
| if ! command -v emulator >/dev/null 2>&1; then | ||
| echo "ERROR: \`emulator\` not found. Install the Android SDK emulator or" \ | ||
| "start an AVD from Android Studio." >&2 | ||
| exit 1 | ||
| fi | ||
|
|
||
| echo "==> Starting emulator: $avd_name" | ||
| emulator -avd "$avd_name" -no-snapshot-load >/dev/null 2>&1 & | ||
| local start | ||
| start="$(date +%s)" | ||
| local timeout="${EMULATOR_BOOT_TIMEOUT:-120}" | ||
| while true; do | ||
| local serial | ||
| serial="$(first_running_emulator || true)" | ||
| if [[ -n "$serial" ]]; then | ||
| DEVICE_SERIAL="$serial" | ||
| return 0 | ||
| fi | ||
| if (( $(date +%s) - start > timeout )); then | ||
| echo "ERROR: Emulator process started but no serial appeared within ${timeout}s." >&2 | ||
| exit 1 | ||
| fi | ||
| sleep 2 | ||
| done | ||
| } | ||
|
|
||
| DEVICE_SERIAL="" | ||
| AVD_NAME="" | ||
| patrol_parse_runner_args usage true patrol_android_emulator_platform_option "$@" | ||
|
|
||
| patrol_resolve_app_root "${BASH_SOURCE[0]}" | ||
|
|
||
| # Pick or boot an emulator. | ||
| if [[ -z "$DEVICE_SERIAL" ]]; then | ||
| DEVICE_SERIAL="$(first_running_emulator || true)" | ||
| if [[ -n "$DEVICE_SERIAL" ]]; then | ||
| echo "==> Auto-selected running emulator: $DEVICE_SERIAL" | ||
| fi | ||
| fi | ||
|
|
||
| if [[ -z "$DEVICE_SERIAL" ]]; then | ||
| if [[ -z "$AVD_NAME" ]]; then | ||
| AVD_NAME="${ANDROID_EMULATOR_AVD:-$(first_listed_avd || true)}" | ||
| fi | ||
| if [[ -z "$AVD_NAME" ]]; then | ||
| echo "ERROR: No running emulator found and no AVD to boot." >&2 | ||
| echo " Start one in Android Studio, pass -a <avd>, or set ANDROID_EMULATOR_AVD." >&2 | ||
| exit 1 | ||
| fi | ||
| start_emulator "$AVD_NAME" | ||
| fi | ||
|
|
||
| wait_for_emulator_boot "$DEVICE_SERIAL" | ||
|
|
||
| if [[ "$DEVICE_SERIAL" != emulator-* ]]; then | ||
| echo "WARNING: $DEVICE_SERIAL does not look like an emulator serial." >&2 | ||
| fi | ||
|
|
||
| patrol_collect_dart_defines | ||
| patrol_build_target_args running | ||
|
|
||
| echo "==> Running Patrol tests on $DEVICE_SERIAL ($BUILD_MODE)..." | ||
| patrol test \ | ||
| --device "$DEVICE_SERIAL" \ | ||
| "$BUILD_MODE" \ | ||
| ${TARGET_ARGS[@]+"${TARGET_ARGS[@]}"} \ | ||
| ${DART_DEFINES[@]+"${DART_DEFINES[@]}"} | ||
|
|
||
| echo "==> Done." | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reused emulator skips boot wait
Medium Severity
If a running emulator is auto-selected or chosen with
-d, the script never callswait_for_emulator_boot, unlike the path that starts a new AVD. Patrol can start whilesys.boot_completedis still unset, leading to flaky or failed instrumentation runs.Reviewed by Cursor Bugbot for commit 7c38e21. Configure here.