Testing purchases in preview
The full purchase and entitlement lifecycle, in the browser, against your real catalog.
The native preview runs your app’s real react-native-purchases JavaScript
against a simulated store built into the simulator. With
RevenueCat connected, that store serves your
project’s actual catalog, so the paywall you ship is the paywall you test.
No device, no sandbox tester account, no App Store Connect products. This is the fastest loop for paywall and entitlement work, and it is exact enough that the same code runs unchanged on a real phone.
What is simulated
The whole client-side purchase lifecycle:
- Offerings.
getOfferingsreturns your current offering, its packages, and priced products, exactly as the SDK would shape them on device. - Purchases.
purchasePackagecompletes the purchase and grants the product’s entitlements. Your paywall’s success path, loading states, and entitlement-gated screens all exercise for real. - Customer info.
getCustomerInfoand customer-info update listeners reflect purchases immediately, so optimistic unlock flows behave the way they will in production. - Restore.
restorePurchasesreturns the purchases made earlier in the session, so you can verify the restore path Apple requires. - Identity.
logInandlogOutswitch the app user id, letting you test sign-out and account-switch behavior around entitlements.
What is deliberately not simulated
Preview purchases never leave the simulator:
- No charges, receipts, or App Store payment sheets. The purchase resolves in-process.
- RevenueCat’s servers never see the purchase, so no webhook fires and no server-side subscription state updates. The unlock you observe in preview is the SDK’s customer-info overlay. Your webhook route and the durable subscription row it writes are exercised later, against sandbox purchases in TestFlight.
- No renewals or billing retries. A simulated subscription stays active for the session; time-based lifecycle events do not fire.
This split is intentional and mirrors the architecture the installed skill builds: the device overlay unlocks instantly, the webhook is durable truth. Preview proves the first half completely and the second half not at all.
Forcing outcomes
A paywall needs its failure paths tested too. Running the simulator standalone
through the rnx CLI, you can supply a
store catalog in rnx.config.ts and set purchaseOutcome: 'cancel' to
make every purchase resolve as user-cancelled, which exercises your cancel
handling without a catalog change. In the Contrast preview the catalog comes
from your connected RevenueCat project instead of a config file.
When the catalog looks wrong
- Empty paywall on a fresh connection. The first preview after connecting can boot before the catalog has been read; it arrives moments later and the preview reboots into it.
- A product is missing. Products without a price set in RevenueCat cannot be simulated and are excluded. Set the price in the RevenueCat dashboard.
- Stale offerings. Catalog edits reach previews on a refresh cycle of about 15 minutes.