Testing and Development

App Store Environments

There are a few aspects to testing purchase screens and purchase behavior that are specific to different app store environments. We discuss some of the most important aspects below.

Apple

In order to simplify testing, Apple's App Store uses accelerated time in their sandbox environments. In the Nami platform, this will affect the following aspects of the platform:

  • Time for subscription purchases to expire

You will encounter these accelerated time periods in simulator testing, device testing, and on TestFlight.

These rules apply to auto-renewable subscriptions. In addition to the accelerated time, test subscriptions only auto-renew a maximum of six times.

For the latest on how Apple handles this, head over to their documentation. We've included the rules here as well for reference.

Real DurationAccelerated Duration
1 week3 minutes
1 month5 minutes
2 months10 minutes
3 months15 minutes
6 months30 minutes
1 year1 hour

Testing payments with Nami

Testing payment flows in the App Store for your application can be made easier with Nami.

In addition to the normal StoreKit test flows which all work as expected with the Nami SDK, you can also choose to enable a bypassStore mode, which lets you test payment flows without calling StoreKit under the hood. This lets you test how payments affect your application in the simulator using the real callbacks (such as registering a purchases changed handler) or purchase checks (like checking if a product ID or set of product IDs has been purchased) that would be used for reacting to store purchases.

Because StoreKit is not available for use in testing when in the iOS simulator, byPassStore mode is enabled by default in the simulator.

To enable on device, set bypassStore to be true in the NamiConfiguration object when you initialize the SDK.

let namiConfig = NamiConfiguration(appPlatformID: "YOUR_APP_ID")
namiConfig.logLevel = .info
namiConfig.bypassStore = true
Nami.configure(namiConfig: namiConfig)
NamiConfiguration *namiConfig = [NamiConfiguration configurationForAppPlatformID: @"YOUR_APP_ID"];
[namiConfig setLogLevel:NamiLogLevelInfo];
[namiConfig setBypassStore:true];
    
[Nami configureWithNamiConfig:namiConfig];
var configDict = {
  "appPlatformID-google": "YOUR_GOOGLE_PLATFORM_ID",
  "appPlatformID-apple": "YOUR_APPLE_PLATFORM_ID",
  "logLevel": "INFO",
  "bypassStore": true
};

NativeModules.NamiBridge.configure(configDict);

After that, purchases will route through Nami internally instead of StoreKit. This lets you avoid having to enter a password every time you want to test a purchase, and to test first-time purchases vs. re-subscriptions.

👍

StoreKit Best Practice

StoreKit has no way of clearing out previous purchases. For this reason, it is usually recommended that you make a new testing account for each pass through a complete purchase test.

This takes effect for both local device testing, and for TestFlight builds so carefully consider which way you want TestFlight users testing purchases before including bypassStore in a TestFlight build.

Enabling this flag also lets you include purchases into XCUITests or unit tests, which may not be possible depending on how or where you do automated testing.

The byPassStore flag is disabled automatically when in a production app on the App Store.

Once you have byPassStore enabled, you can add the code as you normally would handle purchases and will get the same kinds of call flows from Nami that you would from a real StoreKit purchase - it will give you a pending, then purchased signal if you have a purchase handler set up.

Like a real purchase, byPassStore purchases will remain for products that are permanent purchases. In order to clear out test purchases, you can call:

NamiPurchaseManager.clearBypassStorePurchases()
[NamiPurchaseManager clearBypassStorePurchases];
NativeModules.NamiPurchaseManager.clearBypassStorePurchases();

This call will clear purchases made by this bypass mechanism - note that it will not clear out Apple sandbox purchases when running on a device.

👍

Nami Best Practice

We recommend you add a call to clearBypassStorePurchases on app open any time you are using byPassStore. This will ensure that each app run gets a clean test environment.

Note that if you want to test purchase behavior over multiple app runs, you should not include clearBypassStorePurchases.

You can also use clearBypassStorePurchases in conjunction with XCUITests or unit tests to help clear testing purchases made.

For subscription products that can expire, bypassStore uses the same shortened expiration for subscriptions - see the previous chart for times. The time period of the subscription closest to one of those durations determines how much time a subscription expiration takes. The Apple sandbox will automatically renew a subscription five times before expiring. Currently, the Nami framework will just expire without renewal when the subscription is over, at the accelerated rate.

Note that the bypassStore makes testing purchases much easier, but you should always still do some testing with the Apple Sandbox on device - the Nami SDK is a simplification of real-world response from StoreKit, but StoreKit timing of purchases and messaging flows can be different in more complex situations.