Skip to content

v0.0.4 — experimental preview

Choose a tag to compare

@enzomanuelmangano enzomanuelmangano released this 17 May 21:13
· 76 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.

Second preview release. Headline: native UIKit / SwiftUI component coverage.
Every common native iOS UI piece a React Native app uses is now driven from
Ennio end-to-end, including the iOS 26 SwiftUI-hosted variants where the
legacy UIKit class is gone from the view tree.

What's new

Native component handlers (Unix-domain control socket)

All routed through a new in-app socket so the handler isn't queued behind a
busy JS thread.

Component Mechanism Why
UITabBarController (bottom tabs) selectedIndex via UITabBarControllerDelegate (faster path) iOS 26 liquid-glass tab bar takes 2 s+ when routed through CDP — socket bypass makes it ~3 ms
UIAlertController walk window scenes + invoke UIAlertAction.handler alert lives on its own UIWindowLevelAlert window
Header items (headerLeft / headerRight) existing getViewWindowFrame + HID tap RNScreens custom views are reachable in the tree
UIRefreshControl pull-to-refresh two consecutive HID swipes single swipe is flaky on iOS 26 simulator
UIPickerView (@react-native-picker/picker) selectRow:inComponent: + delegate notify HID swipes against wheels are unreliable
UISearchBar (iOS 26 SwiftUI host) walk for UISearchBarTextField (the surviving private text-field class) iOS 26 replaced UISearchBar with InlineSearchBarViewRepresentation
UISegmentedControl setSelectedSegmentIndex: + UIControlEventValueChanged text-tap retry loop was ~14 s per tap
UIDatePicker spinner multi-component picker walk inner 3-wheel UIPickerView reachable via the same picker handler

Runner

  • tap() text-only fast-paths chained in order: tab → search-bar focus → segmented → picker → alert → HID
  • inputText / eraseText auto-route to native UISearchBar ops when a search field is focused
  • Per-flow profile summary in verbose mode (bucket / count / total / avg / pct)
  • Per-step Δ column in --verbose log so the slow step is obvious
  • HID daemon gains key, keyrep, and text ops — eraseText: 50 drops from ~8 s of subprocess spawns to ~50 ms in one gRPC call

Cross-version verified

iOS 26 (iPhone Air) full suite: 41 / 41 PASS.
iOS 18.5 (iPhone 16 Pro) native subset: 7 / 7 PASS.

Install

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

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

Limitations

  • iOS only. Android scaffolding exists but no runtime.
  • Metro must be running. No Metro → no Hermes Inspector → CLI errors out.
  • Bridgeless / Fabric only. Old-architecture RN is not supported.
  • iOS 26 SwiftUI-hosted components. The search-bar handler walks
    UISearchBarTextField rather than UISearchBar; if Apple migrates more
    components similarly (segmented control, picker) the same workaround pattern
    applies.

Inventory not yet covered

  • UIMenu / UIContextMenuInteraction / zeego dropdown — out-of-process UI,
    needs private accessibility-audit APIs; deferred to a separate branch.
  • Native UIActionSheet (deprecated).
  • Apple Pay (PKPaymentAuthorizationViewController) — system sheet, can't be
    driven from the app process.

Full Changelog: v0.0.3...v0.0.4