chore: make Maestro E2E tests more stable (iOS + Android) - #13789
chore: make Maestro E2E tests more stable (iOS + Android)#13789MounirDhahri wants to merge 11 commits into
Conversation
The 'Prefetch app associations' step opens URLs on the simulator via xcrun simctl openurl, which hits the real network. When artsy.net is slow the call times out (NSPOSIXErrorDomain code 60) and, under set -e, fails the whole job before any test runs — a common source of flaky iOS Maestro runs. Wrap each prefetch in a retry loop that never fails the step, preserving the universal-link warm-up without letting it tank the run. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]> Assisted-by: Claude:Opus-4.8 [claude-code]
The post-auth HomeView assertions used a bare assertVisible with Maestro's short default timeout, so a slow post-login render (cold network fetch) intermittently failed with 'Assertion is false: id: search-button is visible'. Replace with extendedWaitUntil at a 30s timeout in login, signup and the deeplinks HomeView smoke check. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]> Assisted-by: Claude:Opus-4.8 [claude-code]
Maestro's local CLI has no built-in retry-on-failure (only Maestro Cloud does), so whole-flow retry is done in the shard wrapper. E2E flows depend on the real network and universal-link resolution, so a single transient failure shouldn't fail the run. Retry each flow once from a clean launch before marking the shard failed. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]> Assisted-by: Claude:Opus-4.8 [claude-code]
Running 'maestro test' locally on Maestro 2.x failed with 'Commands Section Required' because e2e/config.yml carried an 'appId:' + '---' header, so newer Maestro parsed everything after '---' as a flow's command list and found 'flows:' instead. A workspace config takes only the flows block (each flow already declares its own appId). CI is unaffected — it runs individual flow files, not this config. Also fix the README run commands to 'maestro test e2e/'. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]> Assisted-by: Claude:Opus-4.8 [claude-code]
CI ran Maestro 1.40.0 while local dev is on 2.6.1, so behavior diverged and the workspace config.yml that works locally differed from CI. Align iOS CI to 2.6.1. Android is left on 1.40.0 for now (out of scope; not validated here). Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]> Assisted-by: Claude:Opus-4.8 [claude-code]
deeplinks.yml is structurally the flakiest flow: it round-trips through Safari and depends on live universal-link resolution and real network data. It still runs and retries, but a final failure now warns instead of failing the shard, so a transient deeplink issue no longer tanks the whole iOS suite. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]> Assisted-by: Claude:Opus-4.8 [claude-code]
Add an End-to-End Testing section to AGENTS.md covering how to run flows locally, the CI Maestro version pin, the shard retry / non- blocking behavior, and guidance for writing stable flows. Link e2e/README.md from Further Documentation. CLAUDE.md inherits via @AGENTS.md import. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
The native in-app review prompt fires on the 5th app launch and overlays the UI, intermittently blocking E2E assertions (e.g. the post-signup HomeView search-button). Skip it when the useMaestroInit launch argument is set, matching how push and onboarding prompts are already suppressed. Add a jest mock for react-native-launch-arguments so callers (HomeView) don't hit the native linking error. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]> Assisted-by: Claude:Opus-4.8 [claude-code]
Match the iOS bump so both platforms run the same Maestro version as local dev, avoiding local/CI behavior drift. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]> Assisted-by: Claude:Opus-4.8 [claude-code]
Attach the ~/.maestro/tests output (screenshots + command logs) as a GitHub Actions artifact when a shard fails, so failures are debuggable directly from the run page. Uses if: failure() so nothing is uploaded on green runs, and a per-shard artifact name to stay unique. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]> Assisted-by: Claude:Opus-4.8 [claude-code]
On Maestro 2.6.1 with Xcode 26, the first XCTest driver install on a freshly-created simulator can be slow and intermittently trips the 120s timeout (IOSDriverTimeoutException). Double the budget to 240s so a slow-but-healthy cold driver install doesn't fail the run. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
This PR contains the following changes:
|
Code ReviewSummaryThis PR stabilizes the Maestro E2E suite (iOS + Android) by addressing several distinct flakiness sources: making the iOS app-association prefetch non-fatal, replacing bare Issues FoundNo blocking issues. The changes are well-scoped, each commit is independently revertible, and the app-code change follows an established pattern. 🟢 Suggestion — test coverage for the new suppression path ( 🟢 Observation — inline type vs. shared interface ( Areas Reviewed
Notes
Nice, methodical cleanup — the per-bucket commit breakdown in the description makes this easy to reason about. |
This PR resolves []
Description
The iOS Maestro E2E suite has been ~50% flaky on
main. Reading the last ~20 runs, the failures fall into three buckets — only one is a real test issue, the other two are infra/timing noise:openurltimeout kills the job (code 60): the "Prefetch app associations" step hits the real network viaxcrun simctl openurl; when artsy.net is slow it times out and, underset -e, fails the whole job before any test runs.search-buttonnot visible after login: the post-auth HomeView assertions used bareassertVisible(short default timeout), so a slow post-login render intermittently failed.deeplinks.ymlround-trips through Safari and depends on live universal-link resolution + real network data — structurally the flakiest flow.search-button). Reproduced locally: the native "Enjoying Artsy?" review card sits on top of HomeView.Each fix is a separate commit so they can be reviewed / reverted independently:
make iOS app-association prefetch non-fatalwait up to 30s for HomeView search-buttonextendedWaitUntilin login/signup/deeplinksretry a failed Maestro flow oncemake config.yml a valid Maestro workspace configCommands Section Requirederrorpin iOS CI Maestro to 2.6.1make deeplinks flow non-blockingsuppress rate-the-app prompt during Maestro runsuseMaestroInitis set (+ jest mock)pin Android CI Maestro to 2.6.1upload Maestro screenshots as artifacts only on failureif: failure()artifact upload of~/.maestro/tests(both platforms)raise iOS Maestro driver startup timeout to 240sIOSDriverTimeoutExceptionon cold driver installs (Xcode 26)document Maestro run commands and flakiness handlingOn failure, each shard now uploads its Maestro screenshots + command logs as a GitHub Actions artifact (
maestro-<platform>-shard-N) — findable directly from the run page, and nothing is uploaded on green runs.Several fixes live in shared files (the flow YAMLs,
run_maestro_shard, and the cross-platform rate-prompt suppression), so Android benefits too — its occasional failures were the same short-timeoutsearch-buttonassertion plus emulator infra noise.Follow-up work:
deeplinks.ymlbeing non-blocking means a real deeplink regression only shows as a⚠️in the shard log rather than failing CI. Android's residual flakiness is emulatorColorBufferGPU errors (infra), mitigated by the per-flow retry.PR Checklist
To the reviewers 👀
Changelog updates
Changelog updates
Dev changes
Need help with something? Have a look at our docs, or get in touch with us.
Assisted-by: Claude:Opus-4.8