wix / Detox

Gray box end-to-end testing and automation framework for mobile apps
https://wix.github.io/Detox/
MIT License
11.23k stars 1.92k forks source link

Setting up StoreKit environment with configuration file in Xcode 12 #2345

Closed sercand closed 4 years ago

sercand commented 4 years ago

Is your feature request related to a problem? Please describe. Testing IAP flow is impossible with current Detox. Another issue we face is we may not receive the IAP product prices during the test which causes flakiness.

Describe the solution you'd like Apple introduced StoreKit Testing on the latest iOS 14 and Xcode 12. By adding a Configuration.storekit file and selecting it on the Run section of the scheme, we can provide the IAP list. Although using StoreKit configuration fixes the not connecting to AppStore on the Xcode run, it does not affect detox test run.

I don't know if providing complex StoreKit scenarios is possible at all but allowing passing a StoreKit Configuration file to tests is a huge improvement to the current situation.

sercand commented 4 years ago

After digging in StoreKit configuration, I found a workaround to provide StoreKit configuration during the test.

function findId(systemPath: string) {
  return new Promise<string>((resolve, reject) => {
    glob(
      path.join(systemPath, "/**/Documents/Persistence/storeSystem.db"),
      (err, files) => {
        if (err || !files || files.length === 0) {
          return reject(err);
        }
        const ff = files[0].replace(systemPath, "");
        const regex = /\/?([a-zA-Z0-9-]+)\//;
        resolve(regex.exec(ff)[1]);
      }
    );
  });
}

export async function setupStoreKitConfiguration(
  configFile: string,
  bundleId: string
) {
  const systemPath = path.join(
    os.homedir(),
    "Library/Developer/CoreSimulator/Devices/",
    device.id,
    "data/Containers/Data/System"
  );
  const systemId = await findId(systemPath);
  const dataPath = path.join(
    systemPath,
    systemId,
    "Documents/Persistence/Octane/",
    bundleId
  );
  fs.mkdirSync(dataPath, { recursive: true });
  fs.copyFileSync(configFile, path.join(dataPath, "Configuration.storekit"));
}

// USAGE
await setupStoreKitConfiguration("path/to/Configuration.storekit", "com.example.app");
await device.launchApp({});
LeoNatan commented 4 years ago

Hello,

I am not familiar with how StoreKit Testing works in Xcode 12. If you are able to create a native (no RN) skeleton demo project, with a Configuration.storekit file, I can take a look. It is most likely either an environment variable or a launch argument that Xcode provides when launching the app from a scheme with that file linked.

sercand commented 4 years ago

@LeoNatan The sample app that Apple provided for iOS 14 has Configuration.storekit file and in README it explains how to use it: https://developer.apple.com/documentation/app_clips/fruta_building_a_feature-rich_app_with_swiftui

LeoNatan commented 4 years ago

Fruta is one of the buggiest Apple examples, causing consistent SwiftUI crashes. 😂

armartinez commented 4 years ago

@sercand solution worked fine for me but now I can't confirm the purchase since it's a system dialog, any workarounds ?

LeoNatan commented 4 years ago

Unfortunately we won’t be able to offer system alert support until we have an XCUITest support, which is upcoming but will take time.

LeoNatan commented 4 years ago

Interesting, I don't see a launch argument or environment variable for the app process.

LeoNatan commented 4 years ago

The database modification can probably be added to https://github.com/wix/AppleSimulatorUtils

https://github.com/wix/AppleSimulatorUtils/issues/72

Closing this issue in Detox, as it's out of scope. AppleSimUtils is a better place for configuration injection into simulators, while Detox will eventually get the ability to tap on the "Confirm" button using XCUIElement actions. This will take some time.