55# full E2E pass locally. It mirrors what CI does in .github/workflows/e2e.yml.
66#
77# Usage:
8- # ./scripts/run-e2e.sh android [suite]
9- # ./scripts/run-e2e.sh ios [suite]
8+ # ./scripts/run-e2e.sh android [suite ... ]
9+ # ./scripts/run-e2e.sh ios [suite ... ]
1010#
1111# Examples:
12- # ./scripts/run-e2e.sh android # full suite
13- # ./scripts/run-e2e.sh android components # only the components suite
14- # ./scripts/run-e2e.sh ios hooks # only the hooks suite on iOS
12+ # ./scripts/run-e2e.sh android # full suite
13+ # ./scripts/run-e2e.sh android components # only the components suite
14+ # ./scripts/run-e2e.sh ios hooks # only the hooks suite on iOS
15+ # ./scripts/run-e2e.sh android hooks navigation # two categories, one session
1516#
1617# Available suites: full, components, hooks, navigation, layout, styling,
1718# animations, misc.
1819#
20+ # Multiple category suites can be passed at once; they run sequentially in
21+ # a single Maestro session (and against a single emulator/simulator boot).
22+ # CI uses this to shard the Android run into a few balanced groups so no
23+ # single emulator session has to survive the entire 60-flow marathon —
24+ # GitHub-hosted Android emulators grow unstable under ~15 minutes of
25+ # sustained Maestro driving and start reporting "device offline". See
26+ # .github/workflows/e2e.yml and tests/e2e/AGENTS.md.
27+ #
1928# Prerequisites:
2029# - `pn` CLI available (e.g. via `pip install -e .`).
2130# - `maestro` CLI on PATH (https://maestro.dev/).
2433#
2534# The script:
2635# 1. Builds + installs the e2e-suite app via `pn run <platform> --no-logs`.
27- # 2. Picks the right Maestro YAML based on platform + suite .
28- # 3. Runs `maestro test` up to ``MAESTRO_MAX_ATTEMPTS`` times (default
29- # 2) and exits with the last attempt's exit code.
36+ # 2. Resolves each requested suite to its Maestro YAML target .
37+ # 3. Runs `maestro test` (over all targets) up to ``MAESTRO_MAX_ATTEMPTS``
38+ # times (default 2) and exits with the last attempt's exit code.
3039#
3140# A successful run prints "All E2E suites passed." at the end and exits 0.
3241# Any failed flow is reported by Maestro in its standard format; see
@@ -39,7 +48,12 @@ ROOT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
3948cd " $ROOT_DIR "
4049
4150PLATFORM=" ${1:- android} "
42- SUITE=" ${2:- full} "
51+ shift || true
52+ # Remaining args are suite names; default to the full aggregate suite.
53+ SUITES=(" $@ " )
54+ if [[ ${# SUITES[@]} -eq 0 ]]; then
55+ SUITES=(" full" )
56+ fi
4357
4458case " $PLATFORM " in
4559 android|ios) ;;
@@ -65,23 +79,29 @@ case "$PLATFORM" in
6579 ios) APP_ID=" com.pythonnative.ios-template" ;;
6680esac
6781
68- case " $SUITE " in
69- full)
70- if [[ " $PLATFORM " == " android" ]]; then
71- MAESTRO_TARGET=" tests/e2e/android.yaml"
72- else
73- MAESTRO_TARGET=" tests/e2e/ios.yaml"
74- fi
75- ;;
76- components|hooks|navigation|layout|styling|animations|misc)
77- MAESTRO_TARGET=" tests/e2e/suites/${SUITE} .yaml"
78- ;;
79- * )
80- echo " Error: unknown suite '$SUITE '" >&2
81- echo " Available suites: full, components, hooks, navigation, layout, styling, animations, misc" >&2
82- exit 2
83- ;;
84- esac
82+ # Resolve each requested suite to a Maestro YAML target. ``full`` expands
83+ # to the platform's master aggregate; the category names map to the
84+ # per-category suite files under tests/e2e/suites/.
85+ MAESTRO_TARGETS=()
86+ for suite in " ${SUITES[@]} " ; do
87+ case " $suite " in
88+ full)
89+ if [[ " $PLATFORM " == " android" ]]; then
90+ MAESTRO_TARGETS+=(" tests/e2e/android.yaml" )
91+ else
92+ MAESTRO_TARGETS+=(" tests/e2e/ios.yaml" )
93+ fi
94+ ;;
95+ components|hooks|navigation|layout|styling|animations|misc)
96+ MAESTRO_TARGETS+=(" tests/e2e/suites/${suite} .yaml" )
97+ ;;
98+ * )
99+ echo " Error: unknown suite '$suite '" >&2
100+ echo " Available suites: full, components, hooks, navigation, layout, styling, animations, misc" >&2
101+ exit 2
102+ ;;
103+ esac
104+ done
85105
86106printf " \n==> Building e2e-suite app for %s\n" " $PLATFORM "
87107pushd examples/e2e-suite > /dev/null
@@ -90,13 +110,13 @@ popd > /dev/null
90110
91111run_maestro () {
92112 if [[ " $PLATFORM " == " ios" ]]; then
93- maestro --platform ios test -e " APP_ID=$APP_ID " " $MAESTRO_TARGET "
113+ maestro --platform ios test -e " APP_ID=$APP_ID " " ${MAESTRO_TARGETS[@]} "
94114 else
95- maestro test -e " APP_ID=$APP_ID " " $MAESTRO_TARGET "
115+ maestro test -e " APP_ID=$APP_ID " " ${MAESTRO_TARGETS[@]} "
96116 fi
97117}
98118
99- printf " \n==> Running Maestro suite: %s\n" " $MAESTRO_TARGET "
119+ printf " \n==> Running Maestro suite(s) : %s\n" " ${MAESTRO_TARGETS[*]} "
100120
101121# Maestro's iOS XCUITest driver occasionally loses its connection to the
102122# app during long suites and surfaces transient "Application is not
0 commit comments