chore: stabilize Maestro CI#7311
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughThis PR upgrades Maestro to 2.5.1 (Android/iOS), changes Android AVD caching and emulator RAM/options, replaces the Android monkey pre-test step with ChangesMaestro Test Infrastructure Upgrade
Sidebar View Layout Change
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Suggested labels
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Warning Review ran into problems🔥 ProblemsErrors were encountered while retrieving linked issues. Errors (4)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
.github/workflows/maestro-android.yml (1)
41-48:⚠️ Potential issue | 🟠 Major | ⚡ Quick winShard 14 can poison the shared AVD cache, defeating the snapshot optimization for all other shards
The
Cache Android AVDstep has noifcondition, so shard 14 participates in both cache restore and save under the same key (avd-${{ runner.os }}-api34).On a cold run, all 14 shards race to save to that key (GitHub Actions is first-writer-wins). If shard 14 wins, the cache stores only
Pixel_API_34_Keyboard.avd+Pixel_API_34_Keyboard.ini. On subsequent runs:
- Non-keyboard shards see
steps.avd-cache.outputs.cache-hit == 'true'- The "Generate AVD snapshot" step is skipped (its condition checks
cache-hit != 'true')- The test step runs with
force-avd-creation: false— but the expected default-profile AVD is absent from the restored cacheThe behavior of
reactivecircus/android-emulator-runnerwhenforce-avd-creation: falseand the named AVD doesn't exist is unspecified; it may silently cold-boot (losing the optimization) or fail outright. Either way, the caching strategy is silently broken.🐛 Proposed fix — exclude shard 14 from AVD caching
- name: Cache Android AVD + if: ${{ inputs.shard != '14' }} id: avd-cache uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 with: path: | ~/.android/avd/* ~/.android/adb* key: avd-${{ runner.os }}-api34🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.github/workflows/maestro-android.yml around lines 41 - 48, The "Cache Android AVD" step (id: avd-cache, name: Cache Android AVD, key: avd-${{ runner.os }}-api34) must be excluded from shard 14 so it doesn't poison the shared AVD cache; update the step to run only when the shard is not 14 (e.g. add an if condition referencing your matrix/shard variable such as if: matrix.shard != 14) so shard 14 neither restores nor saves to the common key, leaving other shards to generate and cache the full AVD snapshot correctly.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/maestro-android.yml:
- Around line 24-33: The workflow currently uses the jlumbroso/free-disk-space
action with swap-storage: true while configuring the emulator's ram-size: 6144M,
which disables swap and leaves under ~800MB host memory — change either the
swap-storage or ram-size to avoid OOMs: set swap-storage: false to retain the
runner swapfile, or reduce ram-size to 5120M or 4608M so host+emulator fit in
physical RAM; update the keys swap-storage and ram-size in the action usage
(uses: jlumbroso/free-disk-space@...) and apply the same change to the other
occurrences noted (the other blocks referenced) so all workflow entries are
consistent.
In @.github/workflows/maestro-ios.yml:
- Around line 14-15: The comment incorrectly mentions the Android-specific
"dadb"/ADB change; update the comment text that currently references "dadb" and
ADB to an iOS-appropriate note explaining that iOS Maestro uses
idb/libimobiledevice (not ADB) and that the Android-specific CLI 2.5.0 change
does not apply to the iOS workflow; either remove the ADB-specific sentence or
replace it with a short iOS-focused explanation and keep or adjust the release
link as needed so the comment accurately reflects iOS tooling.
---
Outside diff comments:
In @.github/workflows/maestro-android.yml:
- Around line 41-48: The "Cache Android AVD" step (id: avd-cache, name: Cache
Android AVD, key: avd-${{ runner.os }}-api34) must be excluded from shard 14 so
it doesn't poison the shared AVD cache; update the step to run only when the
shard is not 14 (e.g. add an if condition referencing your matrix/shard variable
such as if: matrix.shard != 14) so shard 14 neither restores nor saves to the
common key, leaving other shards to generate and cache the full AVD snapshot
correctly.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: ee299d9c-ce31-45fd-89b1-673983985558
📒 Files selected for processing (3)
.github/scripts/run-maestro.sh.github/workflows/maestro-android.yml.github/workflows/maestro-ios.yml
💤 Files with no reviewable changes (1)
- .github/scripts/run-maestro.sh
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: E2E Build Android / android-build
- GitHub Check: ESLint and Test / run-eslint-and-test
|
Android Build Available Rocket.Chat 4.72.0.108814 |
|
Android Build Available Rocket.Chat 4.72.0.108814 Internal App Sharing: https://play.google.com/apps/test/RQQ8k09hlnQ/ahAO29uNRwjAsJvaiquGjKRmucVItIwkqzqmtF75VX3MLDxOhuznxMA2GxetWxp_dAfRbh33wL0-dHZMTeQVHqchi7 |
|
Android Build Available Rocket.Chat Experimental 4.72.0.108813 |
|
Android Build Available Rocket.Chat Experimental 4.72.0.108813 Internal App Sharing: https://play.google.com/apps/test/RQVpXLytHNc/ahAO29uNTowuRjjHlDYUgXqroMl8epJWmBJOAe-7N_6W5JjAcJyBHu-MfbZDIilMfFnPJkwzs7kKMzme1NVFTUUxnE |
|
iOS Build Available Rocket.Chat Experimental 4.72.0.108816 |
|
Android Build Available Rocket.Chat Experimental 4.72.0.108821 Internal App Sharing: https://play.google.com/apps/test/RQVpXLytHNc/ahAO29uNQLTMEQOTK7Yu4n98ufM0ImDLGPoEI7tdqqt4_8PqA3XXsk_0JhIS1tJIiRPRZJU0Eh3mtvcPjDUgnnZ0rq |
|
Android Build Available Rocket.Chat 4.72.0.108820 Internal App Sharing: https://play.google.com/apps/test/RQQ8k09hlnQ/ahAO29uNQrTqib34jYoZve6A-78lxC3zI5hjF5NuHRtFdGLOxp7tcQ3xwQyvjeTqlI5Lq2c3nCQqQiv5zaR2Rc0VBd |
|
iOS Build Available Rocket.Chat Experimental 4.72.0.108822 |
The Unstar step swiped the action sheet up once and asserted 'Unstar' was visible, while the symmetric Star step uses scrollUntilVisible. When a single swipe didn't fully expand the sheet, 'Unstar' stayed below the fold and the shard failed with "Assertion is false: 'Unstar' is visible". Mirror the Star step so the sheet is scrolled until the item is on screen.
Flows are driven by REST calls (login, users.create, …) that data-setup.js makes to the test server. When the server is down or blips, a flow fails deep inside an evalScript as an opaque "[Failed] <flow>" with no reason in the job log — diagnosing it meant downloading the Maestro artifact and reading maestro.log. Two shell-level signals (run-maestro.sh stdout is the job console, so these render as GitHub annotations without opening logs): - Preflight: probe <server>/api/info before running flows; on non-200 emit a red annotation and exit. A full outage makes every shard fail with the same clear reason instead of 13 mystery flow failures. - Mid-run scan: on failure, grep the local Maestro logs for retryRequest's "Non-retryable error <code>" / connection-error fingerprints and annotate that the failure is likely a server/environment flake.
No code change. Re-run the Build PR matrix to get a fresh stability signal.
…che real Maestro's iOS driver has used XCUITest since 1.18.0 and no longer needs idb-companion to drive the simulator. Verified on Maestro 2.5.1 + iOS 26 with idb absent: launchApp, tapOn, assertVisible (hierarchy read), back and takeScreenshot all pass. Removing `brew tap facebook/fb` + the idb install drops ~110s per iOS shard (the tap triggers a full Homebrew auto-update), ~24 min cumulative macOS runner time per run across 13 shards. Also gate the Maestro install on a cache hit on both platforms. The install script (get.maestro.mobile.dev) rm -rf's ~/.maestro and re-downloads on every run with no "already installed" check, so the existing Cache Maestro step was overwritten and wasted. With the gate, warm runs skip the ~70s download.
…helper - Extract the duplicated Android SDK preinstall block into a .github/actions/preinstall-android-sdk composite action; build-pr.yml (seed job) and maestro-android.yml now reference it instead of copy-pasting the serialized 3x-retried install. - Remove the now-dead per-shard "Generate AVD snapshot" step in maestro-android.yml: e2e-seed-android-avd is a hard needs: and the single writer of the avd-<os>-api34 cache, so the shard restore always hits; the cold-boot fallback creates the AVD on the fly on a rare miss. - Add getAttachmentText() in message/utils.ts as the single source of truth for a quote/reply's displayed text (text || title); Reply.tsx and useQuoteDescriptionLabel.ts both use it so the rendered quote and its VoiceOver label stay in sync.
When the Maestro session never produces a JUnit report (e.g. the iOS XCUITest runner not attaching within MAESTRO_DRIVER_STARTUP_TIMEOUT), run-maestro.sh exited 1 immediately. The existing per-flow rerun loop can't recover that class — it needs a report to know which flows to retry. Retry the whole suite once (MAX_STARTUP_RETRIES, default 1) when no main report is produced, and on exhaustion annotate it as an environment failure rather than an app/test regression. A report that exists with failures is still routed to the per-flow rerun loop unchanged.
- Drop redundant 'simctl launch booted com.apple.springboard' + sleep 5: SpringBoard is already up once bootstatus -b returns, so warming it was pure overhead (~20-90s/shard depending on runner). - Fix UIAnimationDragCoefficient: it is a duration MULTIPLIER, so the previous -float 10 made every UIKit/native-stack transition 10x SLOWER (the opposite of the 'Disabling animations' intent). Set 0.0001 so transitions are near-instant and Maestro never waits on them, mirroring Android's disable-animations. - Start the async simctl boot right after Configure Simulator, before the Java/app-download/E2E-account/Maestro setup steps, so the cold boot overlaps that work instead of running after it.
…o job The step exported $UDID to $GITHUB_ENV but nothing consumed it — Install App uses the 'booted' keyword and Maestro auto-detects the single booted simulator. Removing it so the workflow no longer implies a UDID is needed.
- AVD/SDK snapshot caches are written only on develop and restored read-only by PRs (a PR-scoped cache can't be shared across PRs); a miss cold-boots instead of skipping shards. - Narrow the Maestro cache to bin/lib/deps so stale run logs can't be restored and mis-grepped as server flakes. - Bound each `maestro test` with `timeout -k` and drop the in-script whole-suite startup retry; job timeouts sit just above the in-script bound. - Single-source the shard list for both platforms via a preflight job that fails loud if the flow test-<N> set drifts from the declared 1..14 range; restore the missing test-9 (E2E encryption) shard. - iOS small-screen shard picks the smallest available iPhone (SE) and fails loud if none resolves. - Fail loud when the E2E server URL can't be scraped from data.js, and redact the session token from uploaded Maestro logs. a11y: drop the quoted-reply suffix on Android (TalkBack already enumerates the quote subtree, so the suffix double-announced); correct the FormTextInput note on iOS E2E credential-masking suppression.
The preflight had no needs:, so it ran on every PR open in parallel with lint — before the e2e approval gate. Add needs: [e2e-hold] so it runs only once e2e is approved, alongside the e2e builds. A PR that never opts into e2e no longer burns a runner here, nor gets a red X from the drift guard for a suite it isn't running. The run matrices still consume its output, so nothing downstream changes.
GNU `timeout` bounds each `maestro test`, but it ships as `timeout` only on the Linux (Android) runners; macOS provides it as `gtimeout` (Homebrew coreutils). The hardcoded `timeout` aborted every iOS shard with `timeout: command not found` before Maestro ran, so no JUnit report was produced and the run went red. Resolve whichever binary is present, falling back to running unbounded under the job-level timeout-minutes backstop when neither exists.
The e2e shards used actions/cache with a single static key (maestro-<os>-<version>), so on a cold cache every shard in the first runner wave missed, installed Maestro independently, then raced to save the same key — one won and the rest logged "failed to save: another job may be creating this cache". Whether a shard hit became a function of which runner wave it landed in, not anything deterministic. Populate the cache once in the e2e build jobs (e2e-build-ios on macOS, e2e-build-android on Linux), which already run on the matching runner.os and gate every shard via needs, and switch the shards to actions/cache/restore. Every shard now gets a deterministic hit and only restores: no per-shard install, no first-writer race, no save noise. The build jobs use lookup-only + install/save on miss, so a warm cache is a cheap existence check and they touch the Maestro CDN only on a version bump or eviction. The shards keep their cache-miss Install Maestro step as a fallback. MAESTRO_VERSION is now pinned in the build workflows too; it must stay in sync with the shard workflows or the cache key drifts.
…undle # Conflicts: # app/containers/FormContainer.tsx
The single-use fix in PR #7311 prevents unconditional empty-string appending. However, once any 2FA-protected call completes, this.code retains the TOTP value and leaks it into every subsequent methodCall on that connection, re-introducing the trailing-arg breakage and replaying a spent code. Clear the field immediately after the initial attempt consumes it (no await between write and read, so the retry sees the fresh value and only uses it once). Covered by four test cases: no-2FA path, 2FA prompt + retry, code non-leakage to subsequent calls, and 2FA cancellation.
When the target message id is not yet in the loaded list, the jump loop retries every 600 ms by scrolling to the top to trigger onEndReached. Previously it retried forever, so a deleted or unreachable message held the spinner for the full caller-race timeout (up to 20 s). Track the loaded-message count across retries; if it stays the same for 5 consecutive rounds (~3 s) the target cannot appear — reset and resolve instead of waiting for the backstop timer. Adds useScroll.test.ts covering: no-progress exit, growth keeps retrying, cancel mid-loop, and counter reset between jumps.
| # Single source of the shard list both platforms fan out over, and the guard | ||
| # that keeps it honest: it asserts every flow under .maestro/tests is tagged | ||
| # test-<N> within the declared range and every shard in the range has a flow, | ||
| # then emits the list as JSON for the matrices below. A flow tagged outside | ||
| # the range, or a gap in the range, fails here instead of letting that flow | ||
| # silently never run. No AVD seeding happens on PRs — the avd/sdk caches are | ||
| # written only on develop (build-develop.yml's seed-android-avd); shards | ||
| # restore them read-only and cold-boot on a miss. | ||
| # Gated behind e2e-hold, alongside the e2e builds, so it runs only once e2e is | ||
| # approved — a PR that never opts into e2e neither burns a runner here nor gets | ||
| # a red X from the drift guard for a suite it isn't running. |
There was a problem hiding this comment.
Weird and long comment
| # Single writer of the Maestro install cache the e2e Android shards | ||
| # restore. Keep in sync with maestro-android.yml — the key must match. |
| # Warm the Maestro install cache once here: this job is the single writer | ||
| # of the key the e2e Android shards restore (Linux runner — matching their | ||
| # runner.os — and it gates them via needs). Every shard then gets a | ||
| # deterministic cache hit and only restores: no per-shard install, no | ||
| # concurrent first-writer race. lookup-only skips pulling the payload this | ||
| # job never uses on a warm cache. |
| # Single writer of the Maestro install cache the e2e iOS shards restore. | ||
| # Keep in sync with maestro-ios.yml — the cache key must match exactly. |
| # Warm the Maestro install cache once here: this job is the single writer | ||
| # of the key the e2e iOS shards restore (it runs on macOS — matching their | ||
| # runner.os — and gates them via needs). Every shard then gets a | ||
| # deterministic cache hit and only restores: no per-shard install, no | ||
| # concurrent first-writer race, no "failed to save" noise. lookup-only | ||
| # avoids pulling the ~200 MB payload this job never uses on a warm cache. |
| # Slowest passing shard ~27 min; bounds a wedged session above the in-script | ||
| # timeout -k wrap so a hang fails the job instead of burning the full 6h cap. |
| # 2.5.0 switched gRPC to dadb direct ADB socket — eliminates flaky TCP forwarding (Broken pipe at install). | ||
| # https://github.com/mobile-dev-inc/maestro/releases/tag/cli-2.5.0 |
|
iOS Build Available Rocket.Chat 4.74.0.109084 |
|
Android Build Available Rocket.Chat 4.74.0.109083 Internal App Sharing: https://play.google.com/apps/test/RQQ8k09hlnQ/ahAO29uNQdXkXkqEOf0G7eJdbK_8A8VOCvsyOTnROvyzCSVHlGldJe2okeL0M6o5AtsUjSW3aSc5WFsxkwKDaQAmH4 |
- Version the AVD/SDK cache keys (-v2): shards were restoring a stale
PR-scoped AVD snapshot the emulator rejects ("different AVD
configuration"), forcing every shard to cold boot. The new keys are
seeded exclusively by develop with the current emulator config.
- Raise the Android job timeout 40 -> 55m: a cold-boot main round takes
~31m, leaving no budget for the rerun rounds.
- Dismiss the "System UI isn't responding" ANR dialog before waiting for
the rooms list (cold-boot emulators raise it over the app).
- threads: retry the thread composer input if the IME drops it and wait
for the send button before tapping.
- room: wait for the typed draft to render before navigating away, since
drafts are saved from committed state on unmount.
… label The quote content is already announced on the message-details screen, so duplicating it in the bubble label is redundant for screen-reader users and changes the bubble's accessibility tree shape.
The stale PR-scoped cache entry is deleted directly instead, so the original keys resolve to fresh entries once the develop seed job lands.
Review guideDespite the App changes, ranked by risk
CI half — spot-check rather than deep-read
Context the diff won't show
Fastest competent review: read |
…r before timed step Shard 12 carried ~35 minutes of iOS flow time, exceeding the test step's 30-minute timeout: Room was killed mid-run and Share Message never started. Rebalance flows using per-flow durations measured from a full run, bringing the heaviest iOS shard down to ~15 minutes: - E2E Encryption (heaviest single flow on both platforms) moves to shard 3 and gets it to itself; Server History moves to shard 1, Valid/Invalid Workspace to shard 2 - Room Info, Markdown Click and Share Message move from shard 12 to 9; Threads moves to 13; shard 12 keeps Room + Open room 50+ - Delete Server and Display Perf split from shard 6 onto 7 and 8 Also add an iOS warmup step that installs Maestro's XCUITest driver (~3 minutes on a cold simulator) before the timed test step, so the test step's duration reflects flow execution only.
The warmup pre-installed the XCUITest driver so the 30-minute test step measured flow execution only. After the shard rebalance the heaviest iOS shard runs ~12 min, so the ~3-min driver install fits in the timed step with ample headroom. The step's `|| true` also swallowed driver-install failures, so a broken runner paid the warmup timeout and then failed in the test step anyway. The driver now installs at the start of the timed run, where its failures surface directly.
Proposed changes
Stabilizes the Maestro E2E suite (CI infra + flaky-flow fixes) and folds in the app-code
fixes that unblock specific shards. The CI changes carry no app behavior change; the app
changes are listed first since they're what needs review.
App changes
sdk.tsappended the 2FA code as a trailing''on every DDP call. Harmless until the server'sloadSurroundingMessagesgrew a typedshowThreadMessages: boolean3rd param (RocketChat/Rocket.Chat#39092); the''then failscheck(…, Boolean)→ 500 → the quoted-message jump never navigates. Fix: append the TOTP codeonly when a 2FA flow is in progress (matches the REST path), and clear it as soon as the retry
consumes it — so a spent code never leaks into subsequent calls on the same connection. Non-2FA
calls send exactly their declared params. Unit-tested (
sdk.test.ts: no-2FA path, 2FA prompt +retry, non-leakage, cancellation).
RoomViewraced the list scroll against a fixed 5s cap;off-screen targets on the slow CI emulator exceed it. Raised to 20s as an interim measure.
The scroll-retry loop also now exits early when history stops loading: if the loaded-message
count stays flat for 5 consecutive 600 ms rounds (~3 s), the target can't appear (deleted or
unreachable message), so it resolves instead of holding the spinner for the full 20 s.
Unit-tested (
useScroll.test.ts). The proper O(1) anchored-window rework is not here — itships separately under NATIVE-1224.
FormContainerswapsKeyboardAvoidingView + ScrollViewforKeyboardAwareScrollView(react-native-keyboard-controller, already a dep). Affects the authscreens (Login, Register, ForgotPassword, SendEmailConfirmation, Workspace, NewServer) on both
platforms — see How to test.
Save Password?sheet after credential-field submit that blocks XCUITest. Under
RUNNING_E2E_TESTS=trueon iOS,FormTextInputdeclassifies the field (dropssecureTextEntry/textContentType/autoComplete).Production behavior is unchanged; mirrors what
RegisterViewalready does.SidebarViewwraps theScrollViewin aViewcarryingtestID; Androiddoesn't propagate
testIDfrom aScrollViewto the native tree. (Folded in from fix: restore sidebar-view testID visibility for Maestro #7319.)CI / Maestro stabilization — infra only, no app behavior change
Versions & runners
2.2.0 → 2.5.1(both platforms); 2.5.0's dadb ADB socket kills the AndroidBroken pipeinstall flake.macos-26+ Xcode 26.2.0 to match the iOS-26 build artifact.Android caching / flake fixes
developand restored read-only by PR shards. A single writer means per-PR cache duplication no longer blows the 10 GB Actions cap and LRU-evicts the SDK cache; on a miss a shard cold-boots and installs on the fly.sdkmanagerinstall (clears partial downloads) self-heals theError on ZipFile unknown archiveflake.4 GB → 6 GB; droppedjlumbroso/free-disk-space(shards already start with ~89 GB free) and themonkeywarmup.iOS speed-ups
idb-companion(Maestro's iOS driver uses XCUITest since 1.18.0) — ~110s/shard.Configure Simulator(before Java / app download / E2E account / Maestro setup) so the cold boot overlaps that work; block later onbootstatus -b.Wait for Simulator Ready: dropped the redundantsimctl launch booted com.apple.springboard+sleep 5— SpringBoard is already up oncebootstatus -breturns.UIAnimationDragCoefficient: it is a duration multiplier, so the prior-float 10made every UIKit / native-stack transition 10× slower (the opposite of the "disable animations" intent). Set0.0001so transitions are near-instant and Maestro never waits on them — the iOS analogue of Android'sdisable-animations.iPhone N Pro. No match fails the shard loudly instead of silently falling back.Both platforms
bin/lib/deps), never run logs — so the server-flake log scan can't be fooled by a restored prior run. Shards keep a cache-miss install as a fallback./api/infobefore flows) + mid-run scan of Maestro logs → a server outage/blip renders as a single red job annotation instead of opaque[Failed] <flow>. If the server URL can't be scraped from the test config the job fails loudly (a CI-config error), rather than silently using a fallback.maestro testis bounded in-script (timeout -k 30s 35m) and annotated as an environment failure, with a 40-min job backstop above it. This replaces the old whole-suite startup retry: a run that produces no report now goes red for a human to re-run, rather than auto-retrying and masking real startup breakage. Per-flow rerun rounds3 → 2.&token=…session token the deeplink-login flow writes (the logs ship as a public artifact)..maestro/testsis tagged within the declared range and every shard in the range has a flow, then emits the list as JSON for the matrices. A mistagged or orphaned flow fails fast instead of silently never running.~/.maestro/teststree.Flaky-flow fixes
open-deeplink: anchor the dialog tap to^Open$(unanchoredOpenmatched the iOS 26 alert title).profile: collapse 3 rate-limitedusers.updateOwnBasicInfosubmits into one;hide-keyboardbefore clipped fields.room-actions:scrollUntilVisibletheUnstaritem instead of asserting after one swipe.search-room/discussion/create-team/login: more robust waits andtestID/header-backselectors.Known remaining flaky flows (tracked as follow-ups)
Server / emulator-infra blips (workspace outages, adb socket loss) surface as a single red annotation, not app or test regressions.
Issue(s)
Fixes NATIVE-1123 · NATIVE-1126
Related (deferred, not fixed here): NATIVE-1125 · NATIVE-1128 · NATIVE-1224
How to test or reproduce
NewServer) on iOS and Android after the
KeyboardAwareScrollViewswap — focus each field with thekeyboard open/closed and confirm no clipping or scroll regressions, on phone and tablet.
Screenshots
n/a
Types of changes
Checklist
sdk.test.ts+useScroll.test.ts; CI flows cover the rest)Further comments
The sidebar testID fix was originally #7319, folded here so CI stabilization and its dependency ship
together (#7319 closed). Acceptance is measured over a 10-run window on
developafter this lands.