Skip to content

v0.0.5 — iOS 26 tap reliability

Choose a tag to compare

@enzomanuelmangano enzomanuelmangano released this 19 May 20:03
· 72 commits to main since this release

Warning

Experimental. Ennio is at an early experimental stage. APIs, package
names, internals, and behavior may change without notice between releases.
iOS only. Expect rough edges; do not rely on it for production-critical test
suites yet. The 0.0.x line is a public preview, not a stability commitment.

Third preview. Headline: iOS 26 tap reliability. Three platform-level
races that previously dropped taps during sheet presents, keyboard-up
states, and RNS stack pushes are now closed end-to-end. Example suite
40/40. Habits sign-up-and-delete passes from cold launch to backend
deletion.

What's new

Tap reliability fixes

Issue Fix Where
50 ms held tap claimed by iOS 26 sheet's pan recogniser → tap routed to sheet drag instead of the inner UITextField hidTap durations ≤ 50 ms clamp to instant down/up writer.ts
Missed focus tap silently dropped subsequent HID keystrokes typeText routes through pasteFromClipboard when bound to a testID — landing is keyed by testID, not the focused responder writer.ts
RNS first-touch race: first tap on a freshly mounted screen swallowed by RNSScreenStackView assertVisible / assertNotVisible / inputText auto re-fire the last tap once when the expected post-tap state never arrives maestro-runner.ts
Point taps doubled the sheet's surface offset (tapAt was screen-relative but the runner added the surface origin again) revert surfaceOffset from tapAt — point coordinates stay screen-relative writer.ts
Daemon vs. CLI parity: HID gRPC sometimes rejected fractional coordinates the CLI rounded round float x / y to ints in the persistent HID daemon hid-daemon.py
findLabelMatch picked the outer aggregator Pressable whose AX label happened to contain "Email" (RN auto-aggregates child Text into a parent's accessibilityLabel) rank candidates by label specificityUITextField.placeholder exact > accessibilityLabel exact > CONTAINS — so a text tap on "Email" lands on the leaf RCTUITextField EnnioRuntimeHelper.mm
viewIsHittableAtCenter only walked from hit-test result up toward the target; missed the RN shape where hit-test surfaces the wrapper and the target is one hop down bidirectional walk (target ancestor AND descendant accepted) EnnioRuntimeHelper.mm
getViewWindowFrameByLabel was returning screen-converted coords; sheets live in the same window so the second convertRect:toWindow:nil was a regression drop the screen conversion — return window-relative coords EnnioRuntimeHelper.mm

Podspec

React-FabricComponents was split out of React-Fabric in RN 0.78+; it owns
the TextInput shadow-tree headers. The podspec now adds the public/private
search paths and an explicit dependency so
buildReactNativeFromSource: true builds resolve them.

Cross-version verified

  • Example suite, iOS 26: 40 / 40 PASS.
  • Habits app signup-delete.yaml, iOS 26: cold launch → sign up via email → today tab → settings tab → delete account → back to marketing screen.

Install

bun add @reactiive/ennio react-native-nitro-modules
bun add -d @reactiive/ennio-expo-plugin

Same setup as v0.0.4 — add the plugin to app.json, npx expo prebuild --clean,
npx expo run:ios, write a Maestro YAML.

Limitations

Unchanged from v0.0.4 — iOS only, Bridgeless / Fabric only, Metro must be
running.


Full Changelog: v0.0.4...v0.0.5