Why sign-up emails are awkward to test in React Native
- The link depends on how the app is running.
Linking.createURL('/verify')givesexp://192.168.1.5:8081/--/verifyin Expo Go andmyapp://verifyin a development build. Request an email from one and open it in the other, and nothing happens. - The redirect has to be allowed. Supabase, Firebase and most auth providers only redirect to URLs you’ve listed, so each scheme you use needs adding.
- App links can’t be clicked from a laptop. A desktop browser doesn’t know what to do with
exp://ormyapp://. - Links that launch the app are easy to drop. Handling only the
urlevent misses the link that started the app.
Test it by hand in the simulator or emulator
- Create an address in Proxy Mail QA, with a persona and a generated password if your form needs them.
- Sign up in the app in the iOS simulator or Android emulator. Both share your computer’s clipboard.
- Get the code from the address’s row with Copy.
- Or open the link in the app. Copy it and run
npx uri-scheme open '<link>' --ios(or--android), orxcrun simctl openurl booted '<link>'andadb shell "am start -W -a android.intent.action.VIEW -d '<link>'". The inbox shows the simulator and emulator commands next to app links.
Automate it with Detox
The npm client works in Detox tests:
import { ProxyMailQA } from 'proxymail-qa';
const qa = new ProxyMailQA(); // reads PROXYMAIL_QA_API_KEY
it('signs up with a working magic link', async () => {
const { address } = await qa.createAddress();
await element(by.id('email')).typeText(address);
const submitted = new Date();
await element(by.id('send-link')).tap();
const { value: link } = await qa.waitForLink(address, { type: 'magic_signin', since: submitted, app: true });
await device.openURL({ url: link });
await expect(element(by.id('home'))).toBeVisible();
});
For a code, qa.waitForCode(address, { since: submitted }). To check the email too, qa.checkEmail(address, { since: submitted, expectHost: 'links.example.com' }) returns what failed, with your app’s link domain as expectHost. Appium and Maestro work the same way: see Detox and Appium and Maestro.
What to check in your React Native code
- The email input leaves the address alone.
autoCapitalize="none",autoCorrect={false},keyboardType="email-address"andautoComplete="email". - The code input offers AutoFill on iOS.
textContentType="oneTimeCode". - Cold-start links are handled. With plain React Native, read
Linking.getInitialURL()at startup as well as listening forurlevents. Expo Router and React Navigation’slinkingconfig do both for you. - Each build sends the right link. Build the redirect from the running app (
Linking.createURL) only where that’s what you want, and add each scheme to your auth provider’s allowed redirect URLs. - The link is still single-use. Open it twice: the second time should explain that it was used.
- Links don’t point at your computer. An
exp://link carries your dev server’s address, so it only opens on a device that can reach that server. Web links tolocalhostare flagged: see links that point at localhost.
Using Firebase email-link sign-in through React Native Firebase? See Firebase email-link sign-in on mobile for the native setup it needs.