Deep link tests in Detox open a mobile app through a URL scheme and assert that the routed screen appears. They cover sign-in callbacks, password reset links, order links, and notification URLs that must land on the same screen during an end-to-end run.
Detox can launch the configured app with a url value, which exercises cold-start routing through the app entry point. A Jest spec should assert a visible route-specific element, not just that the app launched, because the URL handler can open the app while still routing to the wrong screen.
An existing Detox project, a configured app binary, and an app route that handles myshop://orders/123 are required before the test can prove routing. Replace the URL, test IDs, and configuration name with values from the project, and add the iOS foreground check only when the app must handle a link while already running.
Related: How to write a first Detox test
Related: How to create a Detox test configuration
Steps to test deep links with Detox:
- Choose one URL and one visible route assertion.
Use a URL that the app can open without production credentials, such as a local order, reset, or profile route seeded for E2E tests. Assert a screen-level testID plus one route-specific value.
- Create a focused deep link spec.
- e2e/deep-link.e2e.js
describe('deep links', () => { it('opens the order screen from a URL', async () => { await device.launchApp({ newInstance: true, url: 'myshop://orders/123', }); await expect(element(by.id('order-detail-screen'))).toBeVisible(); await expect(element(by.id('order-id'))).toHaveText('123'); }); });
device.launchApp({ url }) starts the configured app with the URL so the test can assert the routing result after launch.
Related: How to write a first Detox test
- Add an iOS foreground URL spec when the app must handle links while already running.
- e2e/deep-link-ios.e2e.js
describe('deep links on iOS', () => { it('opens the order screen while the app is running', async () => { await device.launchApp({ newInstance: true }); await device.openURL({ url: 'myshop://orders/123', sourceApp: 'com.apple.mobilesafari', }); await expect(element(by.id('order-detail-screen'))).toBeVisible(); await expect(element(by.id('order-id'))).toHaveText('123'); }); });
device.openURL() is iOS-only. Keep this case in an iOS-specific spec file or omit it from Android-only test runs.
- Run the focused deep link spec with the project configuration.
$ detox test -c ios.sim.debug --reuse e2e/deep-link.e2e.js PASS e2e/deep-link.e2e.js deep links ✓ opens the order screen from a URL (5.1 s) Test Suites: 1 passed, 1 total Tests: 1 passed, 1 totalUse the real configuration name from the project, such as ios.sim.debug or android.emu.debug. Remove --reuse after changing native URL scheme registration or rebuilding the app binary.
- Run the foreground URL spec on an iOS simulator when the app supports that case.
$ detox test -c ios.sim.debug --reuse e2e/deep-link-ios.e2e.js PASS e2e/deep-link-ios.e2e.js deep links on iOS ✓ opens the order screen while the app is running (3.4 s) Test Suites: 1 passed, 1 total Tests: 1 passed, 1 totalA missing order-detail-screen assertion means the app opened but the URL did not reach the expected route, or the test ID is not present on that screen.
Mohd Shakir Zakaria is a cloud architect with deep roots in software development and open-source advocacy. Certified in AWS, Red Hat, VMware, ITIL, and Linux, he specializes in designing and managing robust cloud and on-premises infrastructures.