Skip to content

feat(mobile): implement real multi-device multiremote (RN + Flutter) #446

Description

@goosewobbler

Summary

Implement real multi-device multiremote for @wdio/react-native-service and @wdio/flutter-service — two sims/emulators driven independently within a single session, with commands routed per device. Today only the multiremote capability shape is parsed; the device pool, worker channel, and API attachment are all single-device. This issue tracks building it end-to-end with E2E coverage.

Standalone is the counterpart #445 (already ships); this is the multiremote half.

Current state (starting point)

Launcher — capability-shape parsing only.

  • native-mobile-core/src/launcher.ts flattenCaps unwraps the multiremote { instance: { capabilities } } object; onWorkerStart stamps a device udid onto it.
  • The pool can't give instances distinct devices: onWorkerStart claims one device per worker/cid, and its for (const cap of caps) loop applies that same device to every instance capability — so browserA and browserB get the same appium:udid (launcher.ts ~L105-106). DeviceManager is one-device-per-cid by construction.

Worker — single-instance, no multiremote path.

  • Neither react-native-service/src/service.ts nor flutter-service/src/service.ts before() references isMultiremote/getInstance/instances; both type the arg as a single WebdriverIO.Browser.
  • RN builds one MetroBridge to one host:port; Flutter builds one VmServiceClient + one discovered VM URL.
  • API attaches to whatever browser is passed (browser.reactNative / browser.flutter); on a MultiRemoteBrowser that lands on the aggregate root with a single channel, and execute/mock talk directly to one Hermes/Dart target, bypassing WDIO's per-instance proxying.

Test coverage is capability-shape parsing only (native-mobile-core/test/launcher.spec.ts) — every multiremote case uses a single instance; no two-instance routing, per-instance channel, or API attachment is exercised. The wdio.react-native.conf.ts / wdio.flutter.conf.ts comments reflect this.

Implementation

  1. Launcher / DeviceManager: allocate N distinct devices per multiremote worker (one per instance) and stamp each instance's capability with its own udid.
  2. Worker (both services): branch on browser.isMultiremote, iterate instances, and build a per-instance channel:
    • RN: select the correct Hermes target per device on the Metro inspector (Metro multiplexes targets — current code picks "a" target).
    • Flutter: discover a VM Service URL per device (per-udid).
    • Attach instance.reactNative / instance.flutter per instance (and decide aggregate-root semantics).
  3. E2E + CI: two devices on one runner (iOS simulators most feasible). Mirror the desktop multiremote/ spec layout (e2e/test/tauri/multiremote/*). Note mobile CI is already fragile (cf. Flutter iOS E2E: random per-session CoreSimulator simctl-launch wedge (quarantined in CI) #421 — Flutter iOS simctl wedge).

Notes

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:ciUpdates to Continuous Integrationarea:testsUpdates to testsscope:flutterFlutter service and wdio_flutter Dart contractscope:react-nativeReact Native servicetype:enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions