You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Deep-linking is implemented and exposed for both mobile services, but it's only smoke-tested — the e2e specs assert the Appium command doesn't throw, not that the app actually navigated. This issue tracks proving it end-to-end: register a URL scheme + handler in each fixture, upgrade the e2e to assert navigation, and add a deeplink leg to the required CI gate.
Sibling of #446 (multiremote). Unlike multiremote, the deeplink implementation is real and correct — the gap here is validation, not architecture.
Current state
Implementation (real, works):
packages/native-mobile-core/src/triggerDeeplink.ts fires Appium's cross-platform mobile: deepLink ({ url, package, bundleId }), with an Android am start -a android.intent.action.VIEW -d <url> fallback; resolves app id from appium:appPackage (Android) / appium:bundleId (iOS).
Exposed as browser.reactNative.triggerDeeplink(url) (pure re-export from native-mobile-core) and browser.flutter.triggerDeeplink(url) (switches FLUTTER→NATIVE_APP first, then delegates — correct, since deeplink is a native command). Both typed in native-types.
Unit tests cover command construction + the Android fallback + iOS rethrow (packages/native-mobile-core/test/triggerDeeplink.spec.ts).
Validation gap:
E2e specs exist (e2e/test/react-native/deeplink.spec.ts, e2e/test/flutter/deeplink.spec.ts) but only assert "without throwing" — no navigation proof.
They're TEST_TYPE=deeplink-only, excluded from the default run; the mobile CI gate runs test-type: 'standard' (jobs e2e-react-native-linux, e2e-flutter-linux), so deeplink never runs in required CI.
The fixtures don't register a URL scheme or handler — fixtures/e2e-apps/react-native (no intent-filter / CFBundleURLTypes, no Linking handler) and fixtures/e2e-apps/flutter (no scheme, no app_links/router handler). The spec comments already flag this ("the fixture must register a URL scheme…", "a fuller assertion lands when the fixture wires a deeplink handler").
Implementation
Fixtures — register a scheme + a visible handler:
RN: intent-filter (AndroidManifest) + CFBundleURLTypes (Info.plist); a Linking / React Navigation handler that routes to a distinct screen (e.g. reactnativee2eapp://open/profile → Profile).
Flutter: same scheme registration; an app_links / go_router handler that routes to a distinct screen (e.g. wdioflutter://open/profile).
E2e — assert navigation: after triggerDeeplink(...), assert the target screen is shown (native element present), not merely "no throw". Cover Android + iOS.
(Optional) docs: the README feature tables say deeplink ✅ via mobile: deepLink — accurate about the mechanism, but it implies tested. Once gated, it's fully earned.
Notes
The trigger mechanism is framework-agnostic (OS/Appium-level); there is no framework blocker in RN or Flutter — handling uses each framework's standard API (RN Linking/React Navigation; Flutter app_links/go_router).
Keep e2e on custom schemes (myapp://) — they need no domain infra, unlike https:// universal/app links.
Summary
Deep-linking is implemented and exposed for both mobile services, but it's only smoke-tested — the e2e specs assert the Appium command doesn't throw, not that the app actually navigated. This issue tracks proving it end-to-end: register a URL scheme + handler in each fixture, upgrade the e2e to assert navigation, and add a deeplink leg to the required CI gate.
Sibling of #446 (multiremote). Unlike multiremote, the deeplink implementation is real and correct — the gap here is validation, not architecture.
Current state
Implementation (real, works):
packages/native-mobile-core/src/triggerDeeplink.tsfires Appium's cross-platformmobile: deepLink({ url, package, bundleId }), with an Androidam start -a android.intent.action.VIEW -d <url>fallback; resolves app id fromappium:appPackage(Android) /appium:bundleId(iOS).browser.reactNative.triggerDeeplink(url)(pure re-export fromnative-mobile-core) andbrowser.flutter.triggerDeeplink(url)(switchesFLUTTER→NATIVE_APPfirst, then delegates — correct, since deeplink is a native command). Both typed innative-types.packages/native-mobile-core/test/triggerDeeplink.spec.ts).Validation gap:
e2e/test/react-native/deeplink.spec.ts,e2e/test/flutter/deeplink.spec.ts) but only assert "without throwing" — no navigation proof.TEST_TYPE=deeplink-only, excluded from the default run; the mobile CI gate runstest-type: 'standard'(jobse2e-react-native-linux,e2e-flutter-linux), so deeplink never runs in required CI.fixtures/e2e-apps/react-native(no intent-filter /CFBundleURLTypes, noLinkinghandler) andfixtures/e2e-apps/flutter(no scheme, noapp_links/router handler). The spec comments already flag this ("the fixture must register a URL scheme…", "a fuller assertion lands when the fixture wires a deeplink handler").Implementation
intent-filter(AndroidManifest) +CFBundleURLTypes(Info.plist); aLinking/ React Navigation handler that routes to a distinct screen (e.g.reactnativee2eapp://open/profile→ Profile).app_links/go_routerhandler that routes to a distinct screen (e.g.wdioflutter://open/profile).triggerDeeplink(...), assert the target screen is shown (native element present), not merely "no throw". Cover Android + iOS.deeplinktest-type leg for RN + Flutter to the matrix and toci-statusneeds. Mind mobile CI fragility (cf. Flutter iOS E2E: random per-session CoreSimulator simctl-launch wedge (quarantined in CI) #421/ci(mobile): decouple package smokes from e2e so a flaky e2e can't mask them #430); iOS simulators are the cleaner path —simctl openurl/mobile: deepLinkfire without the real-device Safari prompt.deeplink ✅ via mobile: deepLink— accurate about the mechanism, but it implies tested. Once gated, it's fully earned.Notes
Linking/React Navigation; Flutterapp_links/go_router).myapp://) — they need no domain infra, unlikehttps://universal/app links.