Repository: wix/Detox
Pull request #1778 (2019-11-22 14:50:49)

Respect ANDROID_AVD_HOME environment variable
<!---
Thank you for contributing!
Before submitting a pull request that implements a new functionality or fixing a major bug,
please open an issue first and propose your solution. This way we can discuss before time is 
spent on a solution that may not work for us.

Please check the correct option in the below list and delete the irrelevant one.
For the second option, please fill the issue where the solution has been discussed.
-->
- [x] This is a small change 
---

**Description:**

Android SDK tools respect the `ANDROID_AVD_HOME` environment variable to locate installed emulator instances. This change adds support for that setting when fixing up the `config.ini` file.

noomorph: Could you check this? https://github.com/wix/Detox/pull/1573#discussion_r314241163
lvanengelen: Looked at #1573 and I investigated a bit. I ran `emulator -list-avds` in different configurations and got the following to list the avds correctly:

- With avds inside `/tmp/foo/.android/avd`: `ANDROID_SDK_HOME=/tmp/foo emulator -list-avds`
- With avds inside `/home/len/android/avd`: `ANDROID_EMULATOR_HOME=/home/len/android emulator -list-avds`
- With avds inside `/home/len/android/avd`: `ANDROID_AVD_HOME=/home/len/android/avd`

I will update the branch to reflect this.

Reading #1573 I am not sure why `ANDROID_SDK_HOME` did not work.
lvanengelen: Hmm, I have a hard time deciphering the Jenkins logs to figure out what went wrong during the checks of the second commit. I also fail to understand why it would break while the first commit succeeded. Any pointers are welcome.
lvanengelen: Because the original code also contained `/`, but I can fix that. Also gives me a way of retriggering the checks :) Or is there some easier way than pushing a new commit?
noomorph: If nobody looks earlier, I can look on Monday. 
lvanengelen: That would be nice. As an experiment I force-pushed my initial commit (which completed fine earlier) and the checks also failed, so something seems to have changed in the test setup after my initial commit?

For now I re-pushed my other commits.

Patch:
diff --git a/.gitignore b/.gitignore
index 76b4e679d..42dcc27cf 100644
--- a/.gitignore
+++ b/.gitignore
@@ -103,7 +103,8 @@ ios/xcuserdata/
 # you should judge for yourself, the pros and cons are mentioned at:
 # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
 #
-ios/Pods/
+*/*/ios/Pods/
+*/*/ios/Podfile.lock
 
 # Carthage
 #
@@ -221,6 +222,8 @@ detox/ios_src
 package-lock.json
 /detox/src/devices/detox/notifications/notification.json
 detox/test/artifacts
+/examples/demo-react-native/artifacts
+/examples/demo-react-native-jest/artifacts
 
 ## Final outputs
 
diff --git a/detox/android/detox/src/main/java/com/wix/detox/Detox.java b/detox/android/detox/src/main/java/com/wix/detox/Detox.java
index 665bf2f44..a48ecedbb 100644
--- a/detox/android/detox/src/main/java/com/wix/detox/Detox.java
+++ b/detox/android/detox/src/main/java/com/wix/detox/Detox.java
@@ -11,6 +11,9 @@ import android.os.Looper;
 import androidx.annotation.NonNull;
 import android.util.Base64;
 
+import java.util.Arrays;
+import java.util.List;
+
 import androidx.test.platform.app.InstrumentationRegistry;
 import androidx.test.rule.ActivityTestRule;
 
@@ -71,6 +74,7 @@ public final class Detox {
     private static final String LAUNCH_ARGS_KEY = "launchArgs";
     private static final String DETOX_URL_OVERRIDE_ARG = "detoxURLOverride";
     private static final long ACTIVITY_LAUNCH_TIMEOUT = 10000L;
+    private static final List<String> RESERVED_INSTRUMENTATION_ARGS = Arrays.asList("class", "package", "func", "unit", "size", "perf", "debug", "log", "emma", "coverageFile");
 
     private static ActivityTestRule sActivityTestRule;
 
@@ -234,11 +238,13 @@ public final class Detox {
     }
 
     private static Bundle readLaunchArgs() {
-        final Bundle instrumArgs = InstrumentationRegistry.getArguments();
+        final Bundle instrumentationArgs = InstrumentationRegistry.getArguments();
         final Bundle launchArgs = new Bundle();
 
-        for (String arg : instrumArgs.keySet()) {
-            launchArgs.putString(arg, decodeLaunchArgValue(arg, instrumArgs));
+        for (String arg : instrumentationArgs.keySet()) {
+            if (!RESERVED_INSTRUMENTATION_ARGS.contains(arg)) {
+                launchArgs.putString(arg, decodeLaunchArgValue(arg, instrumentationArgs));
+            }
         }
         return launchArgs;
     }
diff --git a/detox/local-cli/templates/jest.js b/detox/local-cli/templates/jest.js
index 40fb3f7c2..feb3e4d86 100644
--- a/detox/local-cli/templates/jest.js
+++ b/detox/local-cli/templates/jest.js
@@ -14,6 +14,7 @@ const specReporter = require('detox/runners/jest/specReporter');
 
 // Set the default timeout
 jest.setTimeout(120000);
+
 jasmine.getEnv().addReporter(adapter);
 
 // This takes care of generating status logs on a per-spec basis. By default, jest only reports at file-level.
@@ -22,7 +23,7 @@ jasmine.getEnv().addReporter(specReporter);
 
 beforeAll(async () => {
   await detox.init(config);
-});
+}, 300000);
 
 beforeEach(async () => {
   await adapter.beforeEach();
diff --git a/detox/package.json b/detox/package.json
index a72bf83e4..3f5d52d01 100644
--- a/detox/package.json
+++ b/detox/package.json
@@ -1,7 +1,7 @@
 {
   "name": "detox",
   "description": "E2E tests and automation for mobile",
-  "version": "14.9.1",
+  "version": "14.9.2",
   "bin": {
     "detox": "local-cli/cli.js"
   },
diff --git a/detox/src/devices/drivers/AndroidDriver.js b/detox/src/devices/drivers/AndroidDriver.js
index d0cad09a0..36042aa1e 100644
--- a/detox/src/devices/drivers/AndroidDriver.js
+++ b/detox/src/devices/drivers/AndroidDriver.js
@@ -2,7 +2,8 @@ const fs = require('fs');
 const URL = require('url').URL;
 const _ = require('lodash');
 const { encodeBase64 } = require('../../utils/encoding');
-const log = require('../../utils/logger').child({ __filename });
+const logger = require('../../utils/logger');
+const log = logger.child({ __filename });
 const invoke = require('../../invoke');
 const InvocationManager = invoke.InvocationManager;
 const ADB = require('../android/ADB');
@@ -22,6 +23,9 @@ const retry = require('../../utils/retry');
 const { interruptProcess, spawnAndLog } = require('../../utils/exec');
 const AndroidExpect = require('../../android/expect');
 
+const reservedInstrumentationArgs = ['class', 'package', 'func', 'unit', 'size', 'perf', 'debug', 'log', 'emma', 'coverageFile'];
+const isReservedInstrumentationArg = (arg) => reservedInstrumentationArgs.includes(arg);
+
 class AndroidDriver extends DeviceDriverBase {
   constructor(config) {
     super(config);
@@ -202,7 +206,7 @@ class AndroidDriver extends DeviceDriverBase {
   }
 
   async _launchInstrumentationProcess(deviceId, bundleId, rawLaunchArgs) {
-    const launchArgs = this._prepareLaunchArgs(rawLaunchArgs);
+    const launchArgs = this._prepareLaunchArgs(rawLaunchArgs, true);
     const additionalLaunchArgs = this._prepareLaunchArgs({debug: false});
     const serverPort = new URL(this.client.configuration.server).port;
     await this.adb.reverse(deviceId, serverPort);
@@ -252,13 +256,30 @@ class AndroidDriver extends DeviceDriverBase {
     return this.invocationManager.execute(DetoxApi.launchMainActivity());
   }
 
-  _prepareLaunchArgs(launchArgs) {
-    return _.reduce(launchArgs, (result, value, key) => {
+  _prepareLaunchArgs(launchArgs, verbose = false) {
+    const usedReservedArgs = [];
+    const preparedLaunchArgs = _.reduce(launchArgs, (result, value, key) => {
       const valueAsString = _.isString(value) ? value : JSON.stringify(value);
-      const valueEncoded = (key.startsWith('detox')) ? valueAsString : encodeBase64(valueAsString);
+
+      let valueEncoded = valueAsString;
+      if (isReservedInstrumentationArg(key)) {
+        usedReservedArgs.push(key);
+      } else if (!key.startsWith('detox')) {
+        valueEncoded = encodeBase64(valueAsString);
+      }
+
       result.push('-e', key, valueEncoded);
       return result;
     }, []);
+
+    if (verbose && usedReservedArgs.length) {
+      logger.warn([`Arguments [${usedReservedArgs}] were passed in as launchArgs to device.launchApp() `,
+                   'but are reserved to Android\'s test-instrumentation and will not be passed into the app. ',
+                   'Ignore this message if this is what you meant to do. Refer to ',
+                   'https://developer.android.com/studio/test/command-line#AMOptionsSyntax for ',
+                   'further details.'].join(''));
+    }
+    return preparedLaunchArgs;
   }
 }
 
diff --git a/detox/src/devices/drivers/EmulatorDriver.js b/detox/src/devices/drivers/EmulatorDriver.js
index 3cecb1984..1a69c2492 100644
--- a/detox/src/devices/drivers/EmulatorDriver.js
+++ b/detox/src/devices/drivers/EmulatorDriver.js
@@ -133,7 +133,8 @@ class EmulatorDriver extends AndroidDriver {
   }
 
   async _fixEmulatorConfigIniSkinNameIfNeeded(avdName) {
-    const configFile = `${os.homedir()}/.android/avd/${avdName}.avd/config.ini`;
+    const avdHome = environment.getAvdHome();
+    const configFile = path.join(avdHome, `${avdName}.avd`, 'config.ini');
     const config = ini.parse(fs.readFileSync(configFile, 'utf-8'));
 
     if (!config['skin.name']) {
diff --git a/detox/src/utils/environment.js b/detox/src/utils/environment.js
index 2db839c36..834ed3e23 100644
--- a/detox/src/utils/environment.js
+++ b/detox/src/utils/environment.js
@@ -21,6 +21,18 @@ function getAndroidSDKPath() {
   return process.env.ANDROID_SDK_ROOT || process.env.ANDROID_HOME || '';
 }
 
+function getAndroidSDKHome() {
+  return process.env['ANDROID_SDK_HOME'] || os.homedir();
+}
+
+function getEmulatorHome() {
+  return process.env['ANDROID_EMULATOR_HOME'] || path.join(getAndroidSDKHome(), '.android');
+}
+
+function getAvdHome() {
+  return process.env['ANDROID_AVD_HOME'] || path.join(getEmulatorHome(), 'avd');
+}
+
 function getAndroidEmulatorPath() {
   const sdkRoot = getAndroidSDKPath();
   if (!sdkRoot) {
@@ -126,6 +138,7 @@ function getHomeDir() {
 module.exports = {
   getAaptPath,
   getAdbPath,
+  getAvdHome,
   getDetoxVersion,
   getFrameworkPath,
   getAndroidSDKPath,
diff --git a/docs/More.DesignPrinciples.md b/docs/More.DesignPrinciples.md
index 4822f781f..f486939d3 100644
--- a/docs/More.DesignPrinciples.md
+++ b/docs/More.DesignPrinciples.md
@@ -2,12 +2,14 @@
 
 Traditionally, end-to-end tests on mobile are riddled with inherent issues, making the testing process difficult and lowering ROI for developers. We believe that the only way to solve these issues at the core is by changing some of the basic principles of our approach.
 
-* **Detox does not rely on WebDriver** — Detox is built from the ground up to integrate with native layers of your mobile app directly. We try to avoid generic cross-platform interfaces that are often the lowest common denominator. We want to optimize per platform.
+* **Detox does not rely on WebDriver**—Detox is built from the ground up to integrate with native layers of your mobile app directly. We try to avoid generic cross-platform interfaces that are often the lowest common denominator. We want to optimize per platform.
 
 * **Detox does gray box, not black box** — Theoretically, it sounds better to test exactly what you ship as a black box. In practice, switching to gray box allows the test framework to monitor the app from the inside and delivers critical wins like fighting flakiness at the core.
 
 * **Detox relies on EarlGrey and Espresso** — The leading native gray box drivers are developed by Google - EarlGrey for iOS and Espresso for Android. Detox relies on them using a JSON-based reflection mechanism which allows a common JavaScript implementation to invoke their native methods directly.
 
+* **Detox synchronizes with your app's activity** — By being aware of what your app is doing and synchronizing it, Detox times its actions to run only when your app is idle, meaning it has determined that your app has finished work, such as React Native load, animations, network requests, etc. You can further read on this [here](https://github.com/wix/Detox/blob/master/docs/Troubleshooting.Synchronization.md).
+
 * **Friendly Protractor-like API for tests** — Tests in Detox are implemented in human-readable JavaScript and can even be shared between platforms. This easy to use API completely abstracts the complex native driver invocations taking place under the hood.
 
 * **Detox controls devices through low-level APIs** — Let's take iOS simulators for example, which are difficult to control efficiently since multiple concurrent instances aren't supported. Detox uses [AppleSimulatorUtils](https://github.com/wix/AppleSimulatorUtils) (another opensource library by Wix) to work around these issues and support test sharding.
diff --git a/docs/Troubleshooting.Synchronization.md b/docs/Troubleshooting.Synchronization.md
index f2436312e..e79beb5dc 100644
--- a/docs/Troubleshooting.Synchronization.md
+++ b/docs/Troubleshooting.Synchronization.md
@@ -8,6 +8,22 @@ Instead, Detox tries to synchronize the test with the app completely *automatica
 
 When this works it's like magic. You simply execute actions one after the other without worrying about timing, and Detox waits for the app to stabilize before moving to the next test line. If there's an in-flight request to a server, for example, the test will not move forward until the request completes.
 
+### What operations do we try to synchronize with automatically
+
+* **Network requests** - Detox monitors in-flight requests over the network.
+
+* **Main thread (native)** - Detox monitors pending native operations on the main thread (main dispatch queue and main NSOperationQueue).
+
+* **Layout of UI** - Detox monitors UI layout operations. There's also special support for React Native layout which includes the Shadow Queue where [yoga](https://github.com/facebook/yoga) runs.
+
+* **Timers** - Detox monitors timers (explicit asynchronous delays). There's special support for JavaScript timers like setTimeout and setInterval.
+
+* **Animations** - Detox monitors active animations and transitions. There's special support for React Native animations with the Animated library.
+
+* **React Native JavaScript thread** - Detox monitors pending operations on the JavaScript thread in RN apps.
+
+* **React Native bridge** - Detox monitors the React Native bridge and asynchronous messages sent on it.
+
 ### Automatic synchronization works most of the time
 
 It's difficult for an automatic mechanism to be correct in 100% of the cases. There are always exceptions. We are optimizing for the common case so most of your scenarios will not have to deal with synchronization issues.
@@ -22,6 +38,39 @@ When the automatic synchronization mechanism doesn't work, we have 2 potential p
 
 * We are not waiting enough - The test will appear to fail at some point because an element isn't found according to an expectation or isn't found when attempting to perform an action on it. This happens because Detox didn't take some asynchronous operation into account and isn't waiting until it completes.
 
+### Identifying which synchronization mechanism causes us to wait too much
+
+Interactions with the application are synchronized, meaning that they will not execute unless the app is idle. You may encounter situations where the tests just hang. 
+When an action/expectation takes a significant amount of time use this option to print device synchronization status.
+The status will be printed if the action takes more than [value] ms to complete
+
+```
+detox test --debug-synchronization 200
+```
+#### Lower-level Idling Resources Debug (iOS Only)
+
+If `--debug-synchronization` does not provide the necessary information, on iOS you can add the following launch argument to your app (using `launchArgs` in your `launchApp()` call) to enable a very verbose logging of the idling resource system to the system log:
+
+```shell
+-detoxPrintBusyIdleResources YES
+```
+
+You can then obtain this log by running the following command:
+
+```shell
+xcrun simctl spawn booted log stream --level debug --style compact --predicate "category=='EarlGreyStatistics'"
+```
+
+For example, change your `/e2e/init.js` like so:
+
+```js
+await detox.init(config, { launchApp: false });
+await device.launchApp({
+  newInstance: true,
+  launchArgs: { 'detoxPrintBusyIdleResources': 'YES' }
+});
+```
+
 ### Switching to manual synchronization as a workaround
 
 We always have the fail-safe of turning off automatic synchronization and waiting manually by ourselves. This isn't the recommended approach but sometimes we don't have a choice.
@@ -61,55 +110,6 @@ await device.setURLBlacklist([]);
 
 This makes sense only if we're not waiting enough (or if we've disabled automatic synchronization). Use the `waitFor` API to poll until an expectation is met. The API is documented [here](/docs/APIRef.waitFor.md).
 
-### What operations do we try to synchronize with automatically
-
-* **Network requests** - Detox monitors in-flight requests over the network.
-
-* **Main thread (native)** - Detox monitors pending native operations on the main thread (main dispatch queue and main NSOperationQueue).
-
-* **Layout of UI** - Detox monitors UI layout operations. There's also special support for React Native layout which includes the Shadow Queue where [yoga](https://github.com/facebook/yoga) runs.
-
-* **Timers** - Detox monitors timers (explicit asynchronous delays). There's special support for JavaScript timers like setTimeout and setInterval.
-
-* **Animations** - Detox monitors active animations and transitions. There's special support for React Native animations with the Animated library.
-
-* **React Native JavaScript thread** - Detox monitors pending operations on the JavaScript thread in RN apps.
-
-* **React Native bridge** - Detox monitors the React Native bridge and asynchronous messages sent on it.
-
-### Identifying which synchronization mechanism causes us to wait too much
-
-Interactions with the application are synchronized, meaning that they will not execute unless the app is idle. You may encounter situations where the tests just hang. 
-When an action/expectation takes a significant amount of time use this option to print device synchronization status.
-The status will be printed if the action takes more than [value] ms to complete
-
-```
-detox test --debug-synchronization 200
-```
-#### Lower-level Idling Resources Debug (iOS Only)
-
-If `--debug-synchronization` does not provide the necessary information, on iOS you can add the following launch argument to your app (using `launchArgs` in your `launchApp()` call) to enable a very verbose logging of the idling resource system to the system log:
-
-```shell
--detoxPrintBusyIdleResources YES
-```
-
-You can then obtain this log by running the following command:
-
-```shell
-xcrun simctl spawn booted log stream --level debug --style compact --predicate "category=='EarlGreyStatistics'"
-```
-
-For example, change your `/e2e/init.js` like so:
-
-```js
-await detox.init(config, { launchApp: false });
-await device.launchApp({
-  newInstance: true,
-  launchArgs: { 'detoxPrintBusyIdleResources': 'YES' }
-});
-```
-
 ### Tweaking and fine-tuning the synchronization mechanisms
 
 > This isn't exposed yet, TBD
@@ -118,12 +118,12 @@ await device.launchApp({
 
 When facing a synchronization issue and tweaking doesn't help, consider modifying your app. When Detox is having trouble synchronizing due to intense non-stopping activity, it may be a sign that your app is abusing resources.
 
-You can also modify your app for the sake of tests only. If you're building a React Native app, you can use [react-native-repackager](https://github.com/wix/react-native-repackager) to override specific files only in your E2E build.
+You can also modify your app, for the sake of tests only, by using mocking. Read more [here](https://github.com/wix/Detox/blob/master/docs/Guide.Mocking.md).
 
 #### setTimeout and setInterval
 
-By default, Detox is designed to ignore `setInterval` and will only wait for `setTimeout` of up to 1 second. If you have an endless polling loop with short intervals implemented with `setTimeout`, switch the implementation to `setInterval`. If possible, avoid agressive polling in your app altogether, the poor single JavaScript thread we have doesn't like it.
+By default, Detox is designed to ignore `setInterval` and will only wait for `setTimeout` of up to 1.5 seconds. If you have an endless polling loop with short intervals implemented with `setTimeout`, switch the implementation to `setInterval`. If possible, avoid agressive polling in your app altogether, the poor single JavaScript thread we have doesn't like it.
 
 #### Endless looping animations
 
-By default, Detox will wait until animations complete. If you have an endless looping animation, this may cause Detox to hang. In this case, consider turning off the animation synchronization or remove the endless loop in your E2E build with [react-native-repackager](https://github.com/wix/react-native-repackager).
+By default, Detox will wait until animations complete. If you have an endless looping animation, this may cause Detox to hang. In this case, consider turning off the animation synchronization or remove the endless loop in your E2E build with [mocking](https://github.com/wix/Detox/blob/master/docs/Guide.Mocking.md).
diff --git a/examples/demo-native-android/package.json b/examples/demo-native-android/package.json
index 60c5eb76d..c0c96775d 100644
--- a/examples/demo-native-android/package.json
+++ b/examples/demo-native-android/package.json
@@ -1,6 +1,6 @@
 {
   "name": "detox-demo-native-android",
-  "version": "14.9.1",
+  "version": "14.9.2",
   "private": true,
   "scripts": {
     "packager": "react-native start",
@@ -8,7 +8,7 @@
     "e2e": "mocha e2e --opts ./e2e/mocha.opts"
   },
   "devDependencies": {
-    "detox": "^14.9.1",
+    "detox": "^14.9.2",
     "mocha": "^6.1.3"
   },
   "detox": {}
diff --git a/examples/demo-native-ios/package.json b/examples/demo-native-ios/package.json
index dcec0f170..ade39b9c5 100644
--- a/examples/demo-native-ios/package.json
+++ b/examples/demo-native-ios/package.json
@@ -1,9 +1,9 @@
 {
   "name": "detox-demo-native-ios",
-  "version": "14.9.1",
+  "version": "14.9.2",
   "private": true,
   "devDependencies": {
-    "detox": "^14.9.1",
+    "detox": "^14.9.2",
     "mocha": "^6.1.3"
   },
   "detox": {
diff --git a/examples/demo-react-native-detox-instruments/package.json b/examples/demo-react-native-detox-instruments/package.json
index cf63cda7c..05a2cfaee 100644
--- a/examples/demo-react-native-detox-instruments/package.json
+++ b/examples/demo-react-native-detox-instruments/package.json
@@ -1,10 +1,10 @@
 {
   "name": "demo-react-native-detox-instruments",
-  "version": "14.9.1",
+  "version": "14.9.2",
   "private": true,
   "scripts": {},
   "devDependencies": {
-    "detox": "^14.9.1",
+    "detox": "^14.9.2",
     "mocha": "6.x.x"
   },
   "detox": {
diff --git a/examples/demo-react-native-jest/package.json b/examples/demo-react-native-jest/package.json
index d3bbd5087..cb7e70c39 100644
--- a/examples/demo-react-native-jest/package.json
+++ b/examples/demo-react-native-jest/package.json
@@ -1,19 +1,19 @@
 {
   "name": "demo-react-native-jest",
-  "version": "14.9.1",
+  "version": "14.9.2",
   "private": true,
   "scripts": {
     "test:ios-release": "detox test --configuration ios.sim.release -l verbose",
     "test:ios-release-ci": "detox test --configuration ios.sim.release -l verbose --workers 2",
     "test:jest-circus:ios-release": "detox test --configuration ios.sim.release -l verbose -o e2e/config-circus.json",
     "test:jest-circus:ios-release-ci": "detox test --configuration ios.sim.release -l verbose -o e2e/config-circus.json --workers 2",
-    "test:android-release": "detox test --configuration android.emu.release -l verbose",
-    "test:android-release-ci": "detox test --configuration android.emu.release -l verbose --workers 2",
-    "test:jest-circus:android-release": "detox test --configuration android.emu.release -l verbose -o e2e/config-circus.json",
-    "test:jest-circus:android-release-ci": "detox test --configuration android.emu.release -l verbose -o e2e/config-circus.json --workers 2"
+    "test:android-release": "detox test --configuration android.emu.release",
+    "test:android-release-ci": "detox test --configuration android.emu.release -l verbose --workers 2 --headless --record-logs all --take-screenshots all",
+    "test:jest-circus:android-release": "detox test --configuration android.emu.release -o e2e/config-circus.json",
+    "test:jest-circus:android-release-ci": "detox test --configuration android.emu.release -o e2e/config-circus.json -l verbose --workers 2 --headless --record-logs all --take-screenshots all"
   },
   "devDependencies": {
-    "detox": "^14.9.1",
+    "detox": "^14.9.2",
     "jest": "24.8.x",
     "jest-circus": "24.8.x",
     "sanitize-filename": "^1.6.1"
diff --git a/examples/demo-react-native/android/app/build.gradle b/examples/demo-react-native/android/app/build.gradle
index 092a417b2..a0348dd20 100644
--- a/examples/demo-react-native/android/app/build.gradle
+++ b/examples/demo-react-native/android/app/build.gradle
@@ -23,7 +23,7 @@ android {
         versionCode 1
         versionName '1.0'
         ndk {
-            abiFilters "armeabi-v7a", "x86"
+            abiFilters 'armeabi-v7a', 'x86', 'x86_64'
         }
 
         testBuildType System.getProperty('testBuildType', 'debug')
@@ -34,7 +34,7 @@ android {
             reset()
             enable false
             universalApk false  // If true, also generate a universal APK
-            include "armeabi-v7a", "x86"
+            include 'armeabi-v7a', 'x86', 'x86_64'
         }
     }
     signingConfigs {
@@ -54,19 +54,6 @@ android {
             signingConfig signingConfigs.release
         }
     }
-    // applicationVariants are e.g. debug, release
-    applicationVariants.all { variant ->
-        variant.outputs.each { output ->
-            // For each separate APK per architecture, set a unique version code as described here:
-            // http://tools.android.com/tech-docs/new-build-system/user-guide/apk-splits
-            def versionCodes = ["armeabi-v7a": 1, "x86": 2]
-            def abi = output.getFilter(OutputFile.ABI)
-            if (abi != null) {  // null for the universal-debug, universal-release variants
-                output.versionCodeOverride =
-                        versionCodes.get(abi) * 1048576 + defaultConfig.versionCode
-            }
-        }
-    }
 
     packagingOptions {
         exclude 'META-INF/DEPENDENCIES'
diff --git a/examples/demo-react-native/package.json b/examples/demo-react-native/package.json
index 0afadebee..03b8c80b8 100644
--- a/examples/demo-react-native/package.json
+++ b/examples/demo-react-native/package.json
@@ -1,6 +1,6 @@
 {
   "name": "example",
-  "version": "14.9.1",
+  "version": "14.9.2",
   "private": true,
   "scripts": {
     "start": "react-native start",
@@ -9,9 +9,11 @@
     "build:android-debug": "detox build --configuration android.emu.debug",
     "build:android-release": "detox build --configuration android.emu.release",
     "test:ios": "detox test --configuration ios.sim.debug",
-    "test:android-debug": "detox test --configuration android.emu.debug -l verbose",
-    "test:android-release": "detox test --configuration android.emu.release -l verbose",
-    "test:android-explicit-require": "detox test e2eExplicitRequire -c android.emu.release -l verbose --runner-config e2eExplicitRequire/mocha.opts",
+    "test:android-debug": "detox test --configuration android.emu.debug",
+    "test:android-release": "detox test --configuration android.emu.release",
+    "test:android-release-ci": "detox test --configuration android.emu.release -l verbose --headless --record-logs all --take-screenshots all",
+    "test:android-explicit-require": "detox test e2eExplicitRequire -c android.emu.release --runner-config e2eExplicitRequire/mocha.opts",
+    "test:android-explicit-require-ci": "detox test e2eExplicitRequire -c android.emu.release --runner-config e2eExplicitRequire/mocha.opts -l verbose --headless --record-logs all --take-screenshots all",
     "e2e:ios": "npm run build:ios && npm run test:ios",
     "e2e:android-debug": "npm run build:android-debug && npm run test:android-debug",
     "e2e:android-release": "npm run build:android-release && npm run test:android-release"
@@ -21,7 +23,7 @@
     "react-native": "0.60.x"
   },
   "devDependencies": {
-    "detox": "^14.9.1",
+    "detox": "^14.9.2",
     "mocha": "^6.1.3"
   },
   "detox": {
diff --git a/lerna.json b/lerna.json
index 4be9b4a05..c7260377c 100644
--- a/lerna.json
+++ b/lerna.json
@@ -9,9 +9,10 @@
     "examples/demo-react-native",
     "examples/demo-react-native-detox-instruments",
     "examples/demo-react-native-jest",
-    "generation"
+    "generation",
+    "."
   ],
-  "version": "14.9.1",
+  "version": "14.9.2",
   "npmClient": "npm",
   "command": {
     "publish": {
@@ -22,7 +23,8 @@
         "detox-demo-native-ios",
         "detox-demo-react-native",
         "detox-test",
-        "generation"
+        "generation",
+        "."
       ]
     }
   }
diff --git a/package.json b/package.json
index fd376125f..ae0b093f7 100644
--- a/package.json
+++ b/package.json
@@ -3,15 +3,17 @@
     "test:e2e:ios": "pushd detox/test && npm run e2e:ios && popd",
     "test:e2e:android": "pushd detox/test && npm run e2e:android && popd",
     "release": "node scripts/ci.release.js",
-    "package:android": "node scripts/ci.android-release.js"
+    "package:android": "node scripts/ci.android-release.js",
+    "postinstall": "scripts/postinstall.sh"
   },
   "publishConfig": {
     "registry": "https://registry.npmjs.org/"
   },
   "devDependencies": {
+    "chalk": "^2.4.2",
     "lodash": "4.17.x",
     "semver": "5.x.x",
-    "shell-utils": "1.x.x",
-    "chalk": "^2.4.2"
-  }
+    "shell-utils": "1.x.x"
+  },
+  "version": "14.9.2"
 }
diff --git a/scripts/ci.publish.js b/scripts/ci.publish.js
index 9ee7c5a0b..b2a5e60a0 100644
--- a/scripts/ci.publish.js
+++ b/scripts/ci.publish.js
@@ -52,11 +52,15 @@ function publishToNpm() {
 
   const versionType = process.env.RELEASE_VERSION_TYPE;
   const dryRun = process.env.RELEASE_DRY_RUN === "true";
+  const skipNpm = process.env.RELEASE_SKIP_NPM === "true";
   if (dryRun) {
-    log('DRY RUN: Running lerna without publishing');
+    log('DRY RUN: Lerna-publishing without publishing to NPM');
+  }
+  else if (skipNpm) {
+    log('SKIP NPM is set: Lerna-publishing without publishing to NPM');
   }
 
-  exec.execSync(`lerna publish --cd-version "${versionType}" --yes --skip-git ${dryRun ? '--skip-npm' : ''}`);
+  exec.execSync(`lerna publish --cd-version "${versionType}" --yes --skip-git ${(dryRun || skipNpm) ? '--skip-npm' : ''}`);
   exec.execSync('git status');
 }
 
diff --git a/scripts/ci.sh b/scripts/ci.sh
index a79dc34e9..1089a20f3 100755
--- a/scripts/ci.sh
+++ b/scripts/ci.sh
@@ -8,5 +8,5 @@ fi
 
 run_f "lerna bootstrap"
 
-run_f "lerna run --ignore detox-demo* build"
-run_f "lerna run --ignore detox-demo* test"
+run_f "lerna run build"
+run_f "lerna run test"
diff --git a/scripts/demo-projects.android.sh b/scripts/demo-projects.android.sh
index 0639cb014..773041a57 100755
--- a/scripts/demo-projects.android.sh
+++ b/scripts/demo-projects.android.sh
@@ -11,11 +11,16 @@ popd
 
 pushd examples/demo-react-native
 run_f "npm run build:android-release"
-run_f "npm run test:android-release -- --device-launch-args=\"-read-only\" --headless"
-run_f "npm run test:android-explicit-require"
 popd
 
+# this needs to go first because it preloads all the emulators we need,
+# as it runs tests in parallel.
 pushd examples/demo-react-native-jest
-run_f "npm run test:android-release-ci -- --headless"
-run_f "npm run test:jest-circus:android-release-ci -- --headless"
+run_f "npm run test:android-release-ci"
+run_f "npm run test:jest-circus:android-release-ci"
+popd
+
+pushd examples/demo-react-native
+run_f "npm run test:android-release-ci"
+run_f "npm run test:android-explicit-require-ci"
 popd
diff --git a/scripts/install.ios.sh b/scripts/install.ios.sh
index da3664872..0d13fce0a 100755
--- a/scripts/install.ios.sh
+++ b/scripts/install.ios.sh
@@ -2,6 +2,8 @@
 
 $(dirname "$0")/install.sh
 
+gem install xcpretty >/dev/null 2>&1
+
 export CODE_SIGNING_REQUIRED=NO
-brew tap wix/brew
-brew install applesimutils --HEAD
\ No newline at end of file
+HOMEBREW_NO_INSTALL_CLEANUP=1 HOMEBREW_NO_AUTO_UPDATE=1 brew tap wix/brew
+HOMEBREW_NO_INSTALL_CLEANUP=1 HOMEBREW_NO_AUTO_UPDATE=1 brew install applesimutils
diff --git a/scripts/install.sh b/scripts/install.sh
index 93b122aa6..c3bc5d7d9 100755
--- a/scripts/install.sh
+++ b/scripts/install.sh
@@ -2,5 +2,4 @@
 
 npm install -g lerna@2.4.0 >/dev/null 2>&1
 npm install -g react-native-cli >/dev/null 2>&1
-npm install -g detox-cli >/dev/null 2>&1
-gem install xcpretty >/dev/null 2>&1
\ No newline at end of file
+npm install -g detox-cli >/dev/null 2>&1
\ No newline at end of file
diff --git a/scripts/postinstall.sh b/scripts/postinstall.sh
new file mode 100755
index 000000000..c2a738665
--- /dev/null
+++ b/scripts/postinstall.sh
@@ -0,0 +1,6 @@
+#!/bin/bash -e
+
+if [ "$(uname)" == "Darwin" ]; then
+  cd detox/test/ios
+  pod install
+fi
diff --git a/scripts/upload_artifact.sh b/scripts/upload_artifact.sh
index b95ed0223..dc49bceeb 100755
--- a/scripts/upload_artifact.sh
+++ b/scripts/upload_artifact.sh
@@ -1,25 +1,36 @@
-#!/bin/bash -e
+#!/bin/bash
 
 export AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY
 export AWS_SECRET_ACCESS_KEY=$AWS_ACCESS_SECRET
 
 DATE=`date '+%Y-%m-%d_%H-%M-%S'`
 
-if [ $JENKINS_CI ]; then
-  ARTIFACTS_NAME="artifacts_${BUILD_ID}_${DATE}.tar.gz"
-else
-  ARTIFACTS_NAME="artifacts_${TRAVIS_BUILD_ID}_${DATE}.tar.gz"
-fi
-
-if [ -d "detox/test/artifacts" ]; then
-  tar cvzf ${ARTIFACTS_NAME} ./detox/test/artifacts/
+upload_artifacts() {
+  ARTIFACTS_DIR=$1
+  CONTEXT=$2
 
   if [ $JENKINS_CI ]; then
-      echo "Jenkins has build in plugin"
+    ARTIFACTS_NAME="artifacts_${BUILD_ID}_${CONTEXT}_${DATE}.tar.gz"
   else
-      aws s3 cp ${ARTIFACTS_NAME} s3://detox-artifacts/ --region=us-east-1
+    ARTIFACTS_NAME="artifacts_${TRAVIS_BUILD_ID}_${CONTEXT}_${DATE}.tar.gz"
+  fi
+
+  if [ -d "$ARTIFACTS_DIR" ]; then
+    echo "Packing artifacts... (${CONTEXT})"
+    tar cvzf "${ARTIFACTS_NAME}" ${ARTIFACTS_DIR}
+
+    if [ $JENKINS_CI ]; then
+        echo "Upload: Jenkins will upload using built-in plugin"
+    else
+        echo "Uploading artifacts..."
+        aws s3 cp "${ARTIFACTS_NAME}" s3://detox-artifacts/ --region=us-east-1
+    fi
+
+    echo "The artifacts archive is available for download at:"
+    echo "https://detox-artifacts.s3.amazonaws.com/${ARTIFACTS_NAME}"
   fi
+}
 
-  echo "The artifacts archive is available for download at:"
-  echo "https://detox-artifacts.s3.amazonaws.com/${ARTIFACTS_NAME}"
-fi
+upload_artifacts "detox/test/artifacts" "detoxtest"
+upload_artifacts "examples/demo-react-native/artifacts" "rnexample"
+upload_artifacts "examples/demo-react-native-jest/artifacts" "rnexamplejest"


Test patch:
diff --git a/detox/src/devices/drivers/AndroidDriver.test.js b/detox/src/devices/drivers/AndroidDriver.test.js
index f1e5c2111..9891de3ad 100644
--- a/detox/src/devices/drivers/AndroidDriver.test.js
+++ b/detox/src/devices/drivers/AndroidDriver.test.js
@@ -3,6 +3,7 @@ describe('Android driver', () => {
   const deviceId = 'device-id-mock';
   const bundleId = 'bundle-id-mock';
 
+  let logger;
   let exec;
   beforeEach(() => {
     jest.mock('../../utils/encoding', () => ({
@@ -14,6 +15,15 @@ describe('Android driver', () => {
     jest.mock('../../utils/sleep', () => jest.fn().mockResolvedValue(''));
     jest.mock('../../utils/retry', () => jest.fn().mockResolvedValue(''));
 
+    const mockLogger = {
+      warn: jest.fn(),
+    };
+    jest.mock('../../utils/logger', () => ({
+      child: () => mockLogger,
+      ...mockLogger,
+    }));
+    logger = require('../../utils/logger');
+
     jest.mock('../../utils/exec', () => ({
       spawnAndLog: jest.fn().mockReturnValue({
         childProcess: {
@@ -43,6 +53,7 @@ describe('Android driver', () => {
           expect(spawnedFlags[index]).toEqual('-e');
           expect(spawnedFlags[index + 1]).toEqual(key);
           expect(spawnedFlags[index + 2]).toEqual(value);
+          return index + 3;
         }
       }),
     });
@@ -62,15 +73,73 @@ describe('Android driver', () => {
       const spawnArgs = exec.spawnAndLog.mock.calls[0];
       const spawnedFlags = spawnArgs[1];
 
-      expectSpawnedFlag(spawnedFlags).startingIndex(7).toBe({
+      let index = 7;
+      index = expectSpawnedFlag(spawnedFlags).startingIndex(index).toBe({
         key: 'object-arg',
         value: 'base64({"such":"wow","much":"amaze","very":111})'
       });
-      expectSpawnedFlag(spawnedFlags).startingIndex(10).toBe({
+      expectSpawnedFlag(spawnedFlags).startingIndex(index).toBe({
         key: 'string-arg',
         value: 'base64(text, with commas-and-dashes,)'
       });
     });
+
+    // Ref: https://developer.android.com/studio/test/command-line#AMOptionsSyntax
+    it('should whitelist reserved instrumentation args with respect to base64 encoding', async () => {
+      const launchArgs = {
+        // Free arg
+        'user-arg': 'merry christ-nukah',
+
+        // Reserved instrumentation args
+        'class': 'class-value',
+        'package': 'package-value',
+        'func': 'func-value',
+        'unit': 'unit-value',
+        'size': 'size-value',
+        'perf': 'perf-value',
+        'debug': 'debug-value',
+        'log': 'log-value',
+        'emma': 'emma-value',
+        'coverageFile': 'coverageFile-value',
+      };
+
+      await uut.launchApp(deviceId, bundleId, launchArgs, '');
+
+      const spawnArgs = exec.spawnAndLog.mock.calls[0];
+      const spawnedFlags = spawnArgs[1];
+
+      let index = 10;
+      index = expectSpawnedFlag(spawnedFlags).startingIndex(index).toBe({ key: 'class', value: 'class-value' });
+      index = expectSpawnedFlag(spawnedFlags).startingIndex(index).toBe({ key: 'package', value: 'package-value' });
+      index = expectSpawnedFlag(spawnedFlags).startingIndex(index).toBe({ key: 'func', value: 'func-value' });
+      index = expectSpawnedFlag(spawnedFlags).startingIndex(index).toBe({ key: 'unit', value: 'unit-value' });
+      index = expectSpawnedFlag(spawnedFlags).startingIndex(index).toBe({ key: 'size', value: 'size-value' });
+      index = expectSpawnedFlag(spawnedFlags).startingIndex(index).toBe({ key: 'perf', value: 'perf-value' });
+      index = expectSpawnedFlag(spawnedFlags).startingIndex(index).toBe({ key: 'debug', value: 'debug-value' });
+      index = expectSpawnedFlag(spawnedFlags).startingIndex(index).toBe({ key: 'log', value: 'log-value' });
+      index = expectSpawnedFlag(spawnedFlags).startingIndex(index).toBe({ key: 'emma', value: 'emma-value' });
+      expectSpawnedFlag(spawnedFlags).startingIndex(index).toBe({ key: 'coverageFile', value: 'coverageFile-value' });
+    });
+
+    it('should log reserved instrumentation args usage warning, if such have been used', async () => {
+      const launchArgs = {
+        'class': 'class-value',
+      };
+
+      await uut.launchApp(deviceId, bundleId, launchArgs, '');
+
+      expect(logger.warn).toHaveBeenCalled();
+    });
+
+    it('should NOT log instrumentation args usage warning, if none used', async () => {
+      const launchArgs = {
+        'user-arg': 'merry christ-nukah',
+      };
+
+      await uut.launchApp(deviceId, bundleId, launchArgs, '');
+
+      expect(logger.warn).not.toHaveBeenCalled();
+    });
   });
 
   describe('net-port reversing', () => {
diff --git a/detox/src/utils/environment.test.js b/detox/src/utils/environment.test.js
index 0b26b9201..fd70032e4 100644
--- a/detox/src/utils/environment.test.js
+++ b/detox/src/utils/environment.test.js
@@ -37,6 +37,28 @@ describe('Environment', () => {
       await fs.remove(tempSdkPath);
     });
 
+    describe('getAvdHome', () => {
+      const testCases = [
+        [path.join(os.homedir(), '.android', 'avd'), null, null, null],
+        [path.join('homedir', '.android', 'avd'), null, null, 'homedir'],
+        [path.join('emu', 'avd'), null, 'emu', 'homedir'],
+        ['AVD', 'AVD', 'emu', 'homedir'],
+      ];
+
+      it.each(testCases)('should return %j ' + [
+        'if $ANDROID_AVD_HOME = %j',
+        'if $ANDROID_EMULATOR_HOME = %j',
+        'if $ANDROID_SDK_HOME = %j',
+      ].join(' and '), (...args) => {
+
+        process.env['ANDROID_AVD_HOME'] = args[1];
+        process.env['ANDROID_EMULATOR_HOME'] = args[2];
+        process.env['ANDROID_SDK_HOME'] = args[3];
+
+        expect(Environment.getAvdHome()).toBe(args[0]);
+      });
+    });
+
     describe('getAndroidSDKPath', () => {
       it(`should return empty string if $ANDROID_SDK_ROOT and $ANDROID_HOME both are not set`, () => {
         delete process.env.ANDROID_SDK_ROOT;
diff --git a/detox/test/android/app/build.gradle b/detox/test/android/app/build.gradle
index f3e0256e8..e01ec9902 100644
--- a/detox/test/android/app/build.gradle
+++ b/detox/test/android/app/build.gradle
@@ -26,7 +26,7 @@ android {
         versionCode 1
         versionName '1.0'
         ndk {
-            abiFilters 'armeabi-v7a', 'x86'
+            abiFilters 'armeabi-v7a', 'x86', 'x86_64'
         }
         testBuildType System.getProperty('testBuildType', 'debug')
         testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
@@ -38,7 +38,14 @@ android {
         ]
         */
     }
-
+    splits {
+        abi {
+            reset()
+            enable false
+            universalApk false  // If true, also generate a universal APK
+            include 'armeabi-v7a', 'x86', 'x86_64'
+        }
+    }
     signingConfigs {
         release {
             storeFile file("keystore.jks")
@@ -47,7 +54,6 @@ android {
             keyPassword "12345678"
         }
     }
-
     buildTypes {
         release {
             minifyEnabled true
@@ -56,7 +62,6 @@ android {
             signingConfig signingConfigs.release
         }
     }
-
     productFlavors {
         flavorDimensions 'compileRNFromSource'
         fromSource {
@@ -66,7 +71,6 @@ android {
             dimension 'compileRNFromSource'
         }
     }
-
     packagingOptions {
         pickFirst '**/libc++_shared.so'
 
diff --git a/detox/test/android/app/src/main/java/com/example/NativeModule.java b/detox/test/android/app/src/main/java/com/example/NativeModule.java
index 2c8efe84f..b08b0498c 100644
--- a/detox/test/android/app/src/main/java/com/example/NativeModule.java
+++ b/detox/test/android/app/src/main/java/com/example/NativeModule.java
@@ -21,10 +21,9 @@ import com.facebook.react.bridge.WritableMap;
 import com.facebook.react.uimanager.util.ReactFindViewUtil;
 import com.facebook.react.uimanager.util.ReactFindViewUtil.OnMultipleViewsFoundListener;
 
+import java.util.HashSet;
 import java.util.Set;
 
-import androidx.collection.ArraySet;
-
 public class NativeModule extends ReactContextBaseJavaModule {
 
     public static final String NAME = "NativeModule";
@@ -111,34 +110,33 @@ public class NativeModule extends ReactContextBaseJavaModule {
 
     @ReactMethod
     public void spyLongTaps(final String testID) {
-        new LongTapsSpy(testID).spyOnce();
+        new LongTapCrasher(testID).attach();
     }
 
     /**
      * Implementation note: For this purpose, a simpler RN API exists in the same class -
      * {@link ReactFindViewUtil#addViewListener(ReactFindViewUtil.OnViewFoundListener)}.
-     * However, it is found to be a but buggy since it removes all listeners immediately
+     * However, it is found to be a bit buggy since it removes all listeners immediately
      * after being called (i.e. while iterating) with no thread-sync mechanisms to protect it.
-     * If real life (CI), we've genuinely seen on occasions that it throws ConcurrentModificationException
-     * exceptions (and why wouldn't it? - we have a screen with multiple views subscribing and
-     * called concurrently in the ActionsScreen of this demo app; could it be that it is not always called
-     * from the main thread?).
+     * If real life (CI), we've genuinely seen that it throws ConcurrentModificationException exceptions,
+     * on occasions (and why wouldn't it? - our demo app's ActionsScreen has multiple views subscribing and
+     * called concurrently; could it be that not always everything is run in the main thread?).
      * Therefore, we use here {@link ReactFindViewUtil#addViewsListener(OnMultipleViewsFoundListener, Set)},
      * which is too generic but nevertheless allows us to better control when we are to be removed.
      */
-    private static class LongTapsSpy implements OnMultipleViewsFoundListener {
+    private static class LongTapCrasher implements OnMultipleViewsFoundListener {
 
         private final String testID;
 
-        private LongTapsSpy(String testID) {
+        private LongTapCrasher(String testID) {
             this.testID = testID;
         }
 
-        public void spyOnce() {
-            final Set<String> nativeIdsSet = new ArraySet<>(1);
-            nativeIdsSet.add(testID);
+        public void attach() {
+            final Set<String> nativeIds = new HashSet<>();
+            nativeIds.add(testID);
 
-            ReactFindViewUtil.addViewsListener(this, nativeIdsSet);
+            ReactFindViewUtil.addViewsListener(this, nativeIds);
         }
 
         @Override
@@ -146,7 +144,6 @@ public class NativeModule extends ReactContextBaseJavaModule {
             view.setOnLongClickListener(v -> {
                 throw new IllegalStateException("Validation failed: component \"" + testID + "\" was long-tapped!!!");
             });
-
             view.post(() -> ReactFindViewUtil.removeViewsListener(this));
         }
     }
diff --git a/detox/test/e2e/22.launch-args.js b/detox/test/e2e/22.launch-args.test.js
similarity index 68%
rename from detox/test/e2e/22.launch-args.js
rename to detox/test/e2e/22.launch-args.test.js
index d3504a6db..0c4bfb139 100644
--- a/detox/test/e2e/22.launch-args.js
+++ b/detox/test/e2e/22.launch-args.test.js
@@ -7,6 +7,10 @@ describe(':android: Launch arguments', () => {
     await expect(element(by.id(`launchArg-${key}.value`))).toHaveText(expectedValue);
   }
 
+  async function assertNoLaunchArg(launchArgKey) {
+    await expect(element(by.id(`launchArg-${launchArgKey}.name`))).toBeNotVisible();
+  }
+
   it('should handle primitive args', async () => {
     const launchArgs = {
       hello: 'world',
@@ -40,4 +44,22 @@ describe(':android: Launch arguments', () => {
     await assertLaunchArg(launchArgs, 'complex', JSON.stringify(launchArgs.complex));
     await assertLaunchArg(launchArgs, 'complexlist', JSON.stringify(launchArgs.complexlist));
   });
+
+  // Ref: https://developer.android.com/studio/test/command-line#AMOptionsSyntax
+  it('should not pass android instrumentation args through', async () => {
+    const launchArgs = {
+      hello: 'world',
+      debug: false,
+      log: false,
+      size: 'large',
+    };
+
+    await device.launchApp({newInstance: true, launchArgs});
+
+    await element(by.text('Launch Args')).tap();
+    await assertLaunchArg(launchArgs, 'hello', 'world');
+    await assertNoLaunchArg('debug');
+    await assertNoLaunchArg('log');
+    await assertNoLaunchArg('size');
+  });
 });
diff --git a/detox/test/e2e/init-circus.js b/detox/test/e2e/init-circus.js
index 5e2d4ca58..c40b46a75 100644
--- a/detox/test/e2e/init-circus.js
+++ b/detox/test/e2e/init-circus.js
@@ -9,11 +9,11 @@ detoxCircus.getEnv().addEventsListener(assignReporter);
 detoxCircus.getEnv().addEventsListener(specReporter);
 
 // Set the default timeout
-jest.setTimeout(300000);
+jest.setTimeout(120000);
 
 beforeAll(async () => {
   await detox.init(config);
-});
+}, 300000);
 
 beforeEach(async () => {
   await adapter.beforeEach();
diff --git a/detox/test/e2e/init.js b/detox/test/e2e/init.js
index 31e4760a4..8fc85d41e 100644
--- a/detox/test/e2e/init.js
+++ b/detox/test/e2e/init.js
@@ -15,11 +15,11 @@ jasmine.getEnv().addReporter(specReporter);
 jasmine.getEnv().addReporter(assignReporter);
 
 // Set the default timeout
-jest.setTimeout(360000);
+jest.setTimeout(120000);
 
 beforeAll(async () => {
   await detox.init(config);
-});
+}, 300000);
 
 beforeEach(async () => {
   await adapter.beforeEach();
diff --git a/detox/test/index.ios.js b/detox/test/index.ios.js
index 7941e1569..eb21d8ae9 100644
--- a/detox/test/index.ios.js
+++ b/detox/test/index.ios.js
@@ -1,24 +1,12 @@
 import example from './src/app';
 
 import {
-  AppRegistry,
-  PushNotificationIOS
+  AppRegistry
 } from 'react-native';
 
 class exampleIos extends example {
-
-  componentWillMount() {
-    super.componentWillMount();
-    PushNotificationIOS.addEventListener('notification', (notification) => this._onNotification(notification));
-    PushNotificationIOS.addEventListener('localNotification', (notification) => this._onNotification(notification));
-  }
-
   async componentDidMount() {
     super.componentDidMount();
-    const notification = await PushNotificationIOS.getInitialNotification();
-    if (notification) {
-      this.setState({notification: notification.getAlert().title});
-    }
   }
 }
 
diff --git a/detox/test/ios/Podfile b/detox/test/ios/Podfile
new file mode 100644
index 000000000..c3d2d5d11
--- /dev/null
+++ b/detox/test/ios/Podfile
@@ -0,0 +1,47 @@
+platform :ios, '9.0'
+require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'
+
+use_frameworks!
+
+def rn_pods
+  pod 'FBLazyVector', :path => "../node_modules/react-native/Libraries/FBLazyVector"
+  pod 'FBReactNativeSpec', :path => "../node_modules/react-native/Libraries/FBReactNativeSpec"
+  pod 'RCTRequired', :path => "../node_modules/react-native/Libraries/RCTRequired"
+  pod 'RCTTypeSafety', :path => "../node_modules/react-native/Libraries/TypeSafety"
+  pod 'React', :path => '../node_modules/react-native/'
+  pod 'React-Core', :path => '../node_modules/react-native/'
+  pod 'React-CoreModules', :path => '../node_modules/react-native/React/CoreModules'
+  pod 'React-Core/DevSupport', :path => '../node_modules/react-native/'
+  pod 'React-RCTActionSheet', :path => '../node_modules/react-native/Libraries/ActionSheetIOS'
+  pod 'React-RCTAnimation', :path => '../node_modules/react-native/Libraries/NativeAnimation'
+  pod 'React-RCTBlob', :path => '../node_modules/react-native/Libraries/Blob'
+  pod 'React-RCTImage', :path => '../node_modules/react-native/Libraries/Image'
+  pod 'React-RCTLinking', :path => '../node_modules/react-native/Libraries/LinkingIOS'
+  pod 'React-RCTNetwork', :path => '../node_modules/react-native/Libraries/Network'
+  pod 'React-RCTSettings', :path => '../node_modules/react-native/Libraries/Settings'
+  pod 'React-RCTText', :path => '../node_modules/react-native/Libraries/Text'
+  pod 'React-RCTVibration', :path => '../node_modules/react-native/Libraries/Vibration'
+  pod 'React-Core/RCTWebSocket', :path => '../node_modules/react-native/'
+
+  pod 'React-cxxreact', :path => '../node_modules/react-native/ReactCommon/cxxreact'
+  pod 'React-jsi', :path => '../node_modules/react-native/ReactCommon/jsi'
+  pod 'React-jsiexecutor', :path => '../node_modules/react-native/ReactCommon/jsiexecutor'
+  pod 'React-jsinspector', :path => '../node_modules/react-native/ReactCommon/jsinspector'
+  pod 'ReactCommon/jscallinvoker', :path => "../node_modules/react-native/ReactCommon"
+  pod 'ReactCommon/turbomodule/core', :path => "../node_modules/react-native/ReactCommon"
+  pod 'Yoga', :path => '../node_modules/react-native/ReactCommon/yoga'
+
+  pod 'DoubleConversion', :podspec => '../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec'
+  pod 'glog', :podspec => '../node_modules/react-native/third-party-podspecs/glog.podspec'
+  pod 'Folly', :podspec => '../node_modules/react-native/third-party-podspecs/Folly.podspec'
+
+  use_native_modules!
+end
+
+target 'example' do
+  rn_pods
+end
+
+target 'example_ci' do
+  rn_pods
+end
\ No newline at end of file
diff --git a/detox/test/ios/example.xcodeproj/project.pbxproj b/detox/test/ios/example.xcodeproj/project.pbxproj
index 5c407dc49..aeee672cf 100644
--- a/detox/test/ios/example.xcodeproj/project.pbxproj
+++ b/detox/test/ios/example.xcodeproj/project.pbxproj
@@ -7,124 +7,27 @@
 	objects = {
 
 /* Begin PBXBuildFile section */
-		00C302E51ABCBA2D00DB3ED1 /* libRCTActionSheet.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302AC1ABCB8CE00DB3ED1 /* libRCTActionSheet.a */; };
-		00C302E81ABCBA2D00DB3ED1 /* libRCTImage.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302C01ABCB91800DB3ED1 /* libRCTImage.a */; };
-		00C302E91ABCBA2D00DB3ED1 /* libRCTNetwork.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */; };
-		00C302EA1ABCBA2D00DB3ED1 /* libRCTVibration.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302E41ABCB9EE00DB3ED1 /* libRCTVibration.a */; };
-		133E29F31AD74F7200F7D852 /* libRCTLinking.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 78C398B91ACF4ADC00677621 /* libRCTLinking.a */; };
-		139105C61AF99C1200B5F7CC /* libRCTSettings.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 139105C11AF99BAD00B5F7CC /* libRCTSettings.a */; };
-		139FDEF61B0652A700C62182 /* libRCTWebSocket.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 139FDEF41B06529B00C62182 /* libRCTWebSocket.a */; };
 		13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; };
 		13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB11A68108700A75B9A /* LaunchScreen.xib */; };
 		13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
 		13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
-		146834051AC3E58100842450 /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 146834041AC3E56700842450 /* libReact.a */; };
 		3953CC0D229AA78F005DD98C /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 39ED920022916437005EDB56 /* JavaScriptCore.framework */; };
-		396B38541EC9DAC000A226F2 /* libRCTAnimation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 396B38391EC9DAB600A226F2 /* libRCTAnimation.a */; };
 		399B4DEC1ED587120098D2AC /* NativeModule.m in Sources */ = {isa = PBXBuildFile; fileRef = CC17D3311D60A24300267B0C /* NativeModule.m */; };
 		399B4DED1ED587120098D2AC /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; };
 		399B4DEE1ED587120098D2AC /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
-		399B4DF01ED587120098D2AC /* libRCTAnimation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 396B38391EC9DAB600A226F2 /* libRCTAnimation.a */; };
-		399B4DF21ED587120098D2AC /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 146834041AC3E56700842450 /* libReact.a */; };
-		399B4DF31ED587120098D2AC /* libRCTActionSheet.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302AC1ABCB8CE00DB3ED1 /* libRCTActionSheet.a */; };
-		399B4DF51ED587120098D2AC /* libRCTImage.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302C01ABCB91800DB3ED1 /* libRCTImage.a */; };
-		399B4DF61ED587120098D2AC /* libRCTLinking.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 78C398B91ACF4ADC00677621 /* libRCTLinking.a */; };
-		399B4DF71ED587120098D2AC /* libRCTNetwork.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */; };
-		399B4DF81ED587120098D2AC /* libRCTSettings.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 139105C11AF99BAD00B5F7CC /* libRCTSettings.a */; };
-		399B4DF91ED587120098D2AC /* libRCTText.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 832341B51AAA6A8300B99B32 /* libRCTText.a */; };
-		399B4DFA1ED587120098D2AC /* libRCTVibration.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302E41ABCB9EE00DB3ED1 /* libRCTVibration.a */; };
-		399B4DFB1ED587120098D2AC /* libRCTWebSocket.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 139FDEF41B06529B00C62182 /* libRCTWebSocket.a */; };
-		399B4DFC1ED587120098D2AC /* libRCTPushNotification.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 39A077981E5450E700A53A07 /* libRCTPushNotification.a */; };
 		399B4DFE1ED587120098D2AC /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
 		399B4DFF1ED587120098D2AC /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB11A68108700A75B9A /* LaunchScreen.xib */; };
-		39A077AA1E5450FF00A53A07 /* libRCTPushNotification.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 39A077981E5450E700A53A07 /* libRCTPushNotification.a */; };
 		39A34C791E30F3A000BEBB59 /* Detox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 39B044621DAED76400431EC5 /* Detox.framework */; };
 		39B044651DAED76E00431EC5 /* Detox.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 39B044621DAED76400431EC5 /* Detox.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
 		39ED92302291643E005EDB56 /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 39ED920022916437005EDB56 /* JavaScriptCore.framework */; };
-		832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 832341B51AAA6A8300B99B32 /* libRCTText.a */; };
+		4DCC563CBD5151B749FA166E /* Pods_example_ci.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F5E33BEF8B2BE1E1D8A7E8BD /* Pods_example_ci.framework */; };
+		918F6CF9DB3712E966CF1F7C /* Pods_example.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6151F84D0064B768E9F02CEB /* Pods_example.framework */; };
 		CC17D3321D60A24300267B0C /* NativeModule.m in Sources */ = {isa = PBXBuildFile; fileRef = CC17D3311D60A24300267B0C /* NativeModule.m */; };
 		E088C8F41F01585500CC48E9 /* CalendarManager.m in Sources */ = {isa = PBXBuildFile; fileRef = E088C8F31F01585500CC48E9 /* CalendarManager.m */; };
 		E088C8F51F025DE900CC48E9 /* CalendarManager.m in Sources */ = {isa = PBXBuildFile; fileRef = E088C8F31F01585500CC48E9 /* CalendarManager.m */; };
 /* End PBXBuildFile section */
 
 /* Begin PBXContainerItemProxy section */
-		00C302AB1ABCB8CE00DB3ED1 /* PBXContainerItemProxy */ = {
-			isa = PBXContainerItemProxy;
-			containerPortal = 00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */;
-			proxyType = 2;
-			remoteGlobalIDString = 134814201AA4EA6300B7C361;
-			remoteInfo = RCTActionSheet;
-		};
-		00C302BF1ABCB91800DB3ED1 /* PBXContainerItemProxy */ = {
-			isa = PBXContainerItemProxy;
-			containerPortal = 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */;
-			proxyType = 2;
-			remoteGlobalIDString = 58B5115D1A9E6B3D00147676;
-			remoteInfo = RCTImage;
-		};
-		00C302DB1ABCB9D200DB3ED1 /* PBXContainerItemProxy */ = {
-			isa = PBXContainerItemProxy;
-			containerPortal = 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */;
-			proxyType = 2;
-			remoteGlobalIDString = 58B511DB1A9E6C8500147676;
-			remoteInfo = RCTNetwork;
-		};
-		00C302E31ABCB9EE00DB3ED1 /* PBXContainerItemProxy */ = {
-			isa = PBXContainerItemProxy;
-			containerPortal = 00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */;
-			proxyType = 2;
-			remoteGlobalIDString = 832C81801AAF6DEF007FA2F7;
-			remoteInfo = RCTVibration;
-		};
-		139105C01AF99BAD00B5F7CC /* PBXContainerItemProxy */ = {
-			isa = PBXContainerItemProxy;
-			containerPortal = 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */;
-			proxyType = 2;
-			remoteGlobalIDString = 134814201AA4EA6300B7C361;
-			remoteInfo = RCTSettings;
-		};
-		139FDEF31B06529B00C62182 /* PBXContainerItemProxy */ = {
-			isa = PBXContainerItemProxy;
-			containerPortal = 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */;
-			proxyType = 2;
-			remoteGlobalIDString = 3C86DF461ADF2C930047B81A;
-			remoteInfo = RCTWebSocket;
-		};
-		146834031AC3E56700842450 /* PBXContainerItemProxy */ = {
-			isa = PBXContainerItemProxy;
-			containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;
-			proxyType = 2;
-			remoteGlobalIDString = 83CBBA2E1A601D0E00E9B192;
-			remoteInfo = React;
-		};
-		395D2EAC218AFC67002E9C25 /* PBXContainerItemProxy */ = {
-			isa = PBXContainerItemProxy;
-			containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;
-			proxyType = 2;
-			remoteGlobalIDString = EBF21BDC1FC498900052F4D5;
-			remoteInfo = jsinspector;
-		};
-		395D2EAE218AFC67002E9C25 /* PBXContainerItemProxy */ = {
-			isa = PBXContainerItemProxy;
-			containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;
-			proxyType = 2;
-			remoteGlobalIDString = EBF21BFA1FC4989A0052F4D5;
-			remoteInfo = "jsinspector-tvOS";
-		};
-		396B38381EC9DAB600A226F2 /* PBXContainerItemProxy */ = {
-			isa = PBXContainerItemProxy;
-			containerPortal = 396B38301EC9DAB600A226F2 /* RCTAnimation.xcodeproj */;
-			proxyType = 2;
-			remoteGlobalIDString = 134814201AA4EA6300B7C361;
-			remoteInfo = RCTAnimation;
-		};
-		396B383A1EC9DAB600A226F2 /* PBXContainerItemProxy */ = {
-			isa = PBXContainerItemProxy;
-			containerPortal = 396B38301EC9DAB600A226F2 /* RCTAnimation.xcodeproj */;
-			proxyType = 2;
-			remoteGlobalIDString = 2D2A28201D9B03D100D4039D;
-			remoteInfo = "RCTAnimation-tvOS";
-		};
 		39A0778B1E5450E700A53A07 /* PBXContainerItemProxy */ = {
 			isa = PBXContainerItemProxy;
 			containerPortal = 39B0445B1DAED76400431EC5 /* Detox.xcodeproj */;
@@ -132,97 +35,6 @@
 			remoteGlobalIDString = 3928EFA51E47404900C19B6E;
 			remoteInfo = DetoxUserNotificationTests;
 		};
-		39A077971E5450E700A53A07 /* PBXContainerItemProxy */ = {
-			isa = PBXContainerItemProxy;
-			containerPortal = 39A077861E5450E700A53A07 /* RCTPushNotification.xcodeproj */;
-			proxyType = 2;
-			remoteGlobalIDString = 134814201AA4EA6300B7C361;
-			remoteInfo = RCTPushNotification;
-		};
-		39A077991E5450E700A53A07 /* PBXContainerItemProxy */ = {
-			isa = PBXContainerItemProxy;
-			containerPortal = 39A077861E5450E700A53A07 /* RCTPushNotification.xcodeproj */;
-			proxyType = 2;
-			remoteGlobalIDString = 3D05745F1DE6004600184BB4;
-			remoteInfo = "RCTPushNotification-tvOS";
-		};
-		39A34C351E30ED3600BEBB59 /* PBXContainerItemProxy */ = {
-			isa = PBXContainerItemProxy;
-			containerPortal = 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */;
-			proxyType = 2;
-			remoteGlobalIDString = 2D2A283A1D9B042B00D4039D;
-			remoteInfo = "RCTImage-tvOS";
-		};
-		39A34C391E30ED3600BEBB59 /* PBXContainerItemProxy */ = {
-			isa = PBXContainerItemProxy;
-			containerPortal = 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */;
-			proxyType = 2;
-			remoteGlobalIDString = 2D2A28471D9B043800D4039D;
-			remoteInfo = "RCTLinking-tvOS";
-		};
-		39A34C3D1E30ED3600BEBB59 /* PBXContainerItemProxy */ = {
-			isa = PBXContainerItemProxy;
-			containerPortal = 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */;
-			proxyType = 2;
-			remoteGlobalIDString = 2D2A28541D9B044C00D4039D;
-			remoteInfo = "RCTNetwork-tvOS";
-		};
-		39A34C411E30ED3600BEBB59 /* PBXContainerItemProxy */ = {
-			isa = PBXContainerItemProxy;
-			containerPortal = 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */;
-			proxyType = 2;
-			remoteGlobalIDString = 2D2A28611D9B046600D4039D;
-			remoteInfo = "RCTSettings-tvOS";
-		};
-		39A34C451E30ED3600BEBB59 /* PBXContainerItemProxy */ = {
-			isa = PBXContainerItemProxy;
-			containerPortal = 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */;
-			proxyType = 2;
-			remoteGlobalIDString = 2D2A287B1D9B048500D4039D;
-			remoteInfo = "RCTText-tvOS";
-		};
-		39A34C4A1E30ED3600BEBB59 /* PBXContainerItemProxy */ = {
-			isa = PBXContainerItemProxy;
-			containerPortal = 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */;
-			proxyType = 2;
-			remoteGlobalIDString = 2D2A28881D9B049200D4039D;
-			remoteInfo = "RCTWebSocket-tvOS";
-		};
-		39A34C541E30ED3600BEBB59 /* PBXContainerItemProxy */ = {
-			isa = PBXContainerItemProxy;
-			containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;
-			proxyType = 2;
-			remoteGlobalIDString = 2D2A28131D9B038B00D4039D;
-			remoteInfo = "React-tvOS";
-		};
-		39A34C561E30ED3600BEBB59 /* PBXContainerItemProxy */ = {
-			isa = PBXContainerItemProxy;
-			containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;
-			proxyType = 2;
-			remoteGlobalIDString = 3D3C059A1DE3340900C268FA;
-			remoteInfo = yoga;
-		};
-		39A34C581E30ED3600BEBB59 /* PBXContainerItemProxy */ = {
-			isa = PBXContainerItemProxy;
-			containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;
-			proxyType = 2;
-			remoteGlobalIDString = 3D3C06751DE3340C00C268FA;
-			remoteInfo = "yoga-tvOS";
-		};
-		39A34C5A1E30ED3600BEBB59 /* PBXContainerItemProxy */ = {
-			isa = PBXContainerItemProxy;
-			containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;
-			proxyType = 2;
-			remoteGlobalIDString = 3D3CD9251DE5FBEC00167DC4;
-			remoteInfo = cxxreact;
-		};
-		39A34C5C1E30ED3600BEBB59 /* PBXContainerItemProxy */ = {
-			isa = PBXContainerItemProxy;
-			containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;
-			proxyType = 2;
-			remoteGlobalIDString = 3D3CD9321DE5FBEE00167DC4;
-			remoteInfo = "cxxreact-tvOS";
-		};
 		39B044611DAED76400431EC5 /* PBXContainerItemProxy */ = {
 			isa = PBXContainerItemProxy;
 			containerPortal = 39B0445B1DAED76400431EC5 /* Detox.xcodeproj */;
@@ -237,76 +49,6 @@
 			remoteGlobalIDString = 394767961DBF985400D72256;
 			remoteInfo = Detox;
 		};
-		39BD07C62361A5270031C946 /* PBXContainerItemProxy */ = {
-			isa = PBXContainerItemProxy;
-			containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;
-			proxyType = 2;
-			remoteGlobalIDString = EDEBC6D6214B3E7000DD5AC8;
-			remoteInfo = jsi;
-		};
-		39BD07C82361A5270031C946 /* PBXContainerItemProxy */ = {
-			isa = PBXContainerItemProxy;
-			containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;
-			proxyType = 2;
-			remoteGlobalIDString = EDEBC73B214B45A300DD5AC8;
-			remoteInfo = jsiexecutor;
-		};
-		39BD07CA2361A5270031C946 /* PBXContainerItemProxy */ = {
-			isa = PBXContainerItemProxy;
-			containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;
-			proxyType = 2;
-			remoteGlobalIDString = ED296FB6214C9A0900B7C4FE;
-			remoteInfo = "jsi-tvOS";
-		};
-		39BD07CC2361A5270031C946 /* PBXContainerItemProxy */ = {
-			isa = PBXContainerItemProxy;
-			containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;
-			proxyType = 2;
-			remoteGlobalIDString = ED296FEE214C9CF800B7C4FE;
-			remoteInfo = "jsiexecutor-tvOS";
-		};
-		4644B8641F897583003223D4 /* PBXContainerItemProxy */ = {
-			isa = PBXContainerItemProxy;
-			containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;
-			proxyType = 2;
-			remoteGlobalIDString = 139D7ECE1E25DB7D00323FB7;
-			remoteInfo = "third-party";
-		};
-		4644B8661F897583003223D4 /* PBXContainerItemProxy */ = {
-			isa = PBXContainerItemProxy;
-			containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;
-			proxyType = 2;
-			remoteGlobalIDString = 3D383D3C1EBD27B6005632C8;
-			remoteInfo = "third-party-tvOS";
-		};
-		4644B8681F897583003223D4 /* PBXContainerItemProxy */ = {
-			isa = PBXContainerItemProxy;
-			containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;
-			proxyType = 2;
-			remoteGlobalIDString = 139D7E881E25C6D100323FB7;
-			remoteInfo = "double-conversion";
-		};
-		4644B86A1F897583003223D4 /* PBXContainerItemProxy */ = {
-			isa = PBXContainerItemProxy;
-			containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;
-			proxyType = 2;
-			remoteGlobalIDString = 3D383D621EBD27B9005632C8;
-			remoteInfo = "double-conversion-tvOS";
-		};
-		78C398B81ACF4ADC00677621 /* PBXContainerItemProxy */ = {
-			isa = PBXContainerItemProxy;
-			containerPortal = 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */;
-			proxyType = 2;
-			remoteGlobalIDString = 134814201AA4EA6300B7C361;
-			remoteInfo = RCTLinking;
-		};
-		832341B41AAA6A8300B99B32 /* PBXContainerItemProxy */ = {
-			isa = PBXContainerItemProxy;
-			containerPortal = 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */;
-			proxyType = 2;
-			remoteGlobalIDString = 58B5119B1A9E6C1200147676;
-			remoteInfo = RCTText;
-		};
 /* End PBXContainerItemProxy section */
 
 /* Begin PBXCopyFilesBuildPhase section */
@@ -335,12 +77,7 @@
 
 /* Begin PBXFileReference section */
 		008F07F21AC5B25A0029DE68 /* main.jsbundle */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = main.jsbundle; sourceTree = "<group>"; };
-		00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTActionSheet.xcodeproj; path = "../node_modules/react-native/Libraries/ActionSheetIOS/RCTActionSheet.xcodeproj"; sourceTree = "<group>"; };
-		00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTImage.xcodeproj; path = "../node_modules/react-native/Libraries/Image/RCTImage.xcodeproj"; sourceTree = "<group>"; };
-		00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTNetwork.xcodeproj; path = "../node_modules/react-native/Libraries/Network/RCTNetwork.xcodeproj"; sourceTree = "<group>"; };
-		00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTVibration.xcodeproj; path = "../node_modules/react-native/Libraries/Vibration/RCTVibration.xcodeproj"; sourceTree = "<group>"; };
-		139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTSettings.xcodeproj; path = "../node_modules/react-native/Libraries/Settings/RCTSettings.xcodeproj"; sourceTree = "<group>"; };
-		139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTWebSocket.xcodeproj; path = "../node_modules/react-native/Libraries/WebSocket/RCTWebSocket.xcodeproj"; sourceTree = "<group>"; };
+		0FCE2B17362E305AD63D208E /* Pods-example_ci.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-example_ci.debug.xcconfig"; path = "Target Support Files/Pods-example_ci/Pods-example_ci.debug.xcconfig"; sourceTree = "<group>"; };
 		13B07F961A680F5B00A75B9A /* example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = example.app; sourceTree = BUILT_PRODUCTS_DIR; };
 		13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = example/AppDelegate.h; sourceTree = "<group>"; tabWidth = 4; };
 		13B07FB01A68108700A75B9A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = example/AppDelegate.m; sourceTree = "<group>"; tabWidth = 4; };
@@ -348,20 +85,20 @@
 		13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = example/Images.xcassets; sourceTree = "<group>"; };
 		13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = example/Info.plist; sourceTree = "<group>"; };
 		13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = example/main.m; sourceTree = "<group>"; };
-		146833FF1AC3E56700842450 /* React.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = React.xcodeproj; path = "../node_modules/react-native/React/React.xcodeproj"; sourceTree = "<group>"; };
-		396B38301EC9DAB600A226F2 /* RCTAnimation.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTAnimation.xcodeproj; path = "../node_modules/react-native/Libraries/NativeAnimation/RCTAnimation.xcodeproj"; sourceTree = "<group>"; };
 		399B4E061ED587120098D2AC /* example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = example.app; sourceTree = BUILT_PRODUCTS_DIR; };
-		39A077861E5450E700A53A07 /* RCTPushNotification.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTPushNotification.xcodeproj; path = "../node_modules/react-native/Libraries/PushNotificationIOS/RCTPushNotification.xcodeproj"; sourceTree = "<group>"; };
 		39B0445B1DAED76400431EC5 /* Detox.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Detox.xcodeproj; path = ../../ios/Detox.xcodeproj; sourceTree = "<group>"; };
 		39ED920022916437005EDB56 /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
 		39FC9D23202899F90033C11A /* e2e */ = {isa = PBXFileReference; lastKnownFileType = folder; name = e2e; path = ../e2e; sourceTree = "<group>"; };
 		39FC9D24202899F90033C11A /* src */ = {isa = PBXFileReference; lastKnownFileType = folder; name = src; path = ../src; sourceTree = "<group>"; };
-		78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTLinking.xcodeproj; path = "../node_modules/react-native/Libraries/LinkingIOS/RCTLinking.xcodeproj"; sourceTree = "<group>"; };
-		832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTText.xcodeproj; path = "../node_modules/react-native/Libraries/Text/RCTText.xcodeproj"; sourceTree = "<group>"; };
+		6151F84D0064B768E9F02CEB /* Pods_example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_example.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+		66F0F062E8DEDED761A32E62 /* Pods-example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-example.release.xcconfig"; path = "Target Support Files/Pods-example/Pods-example.release.xcconfig"; sourceTree = "<group>"; };
+		AA201D8508E7536D1B2419C4 /* Pods-example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-example.debug.xcconfig"; path = "Target Support Files/Pods-example/Pods-example.debug.xcconfig"; sourceTree = "<group>"; };
+		AC4951A69652648DAD57681D /* Pods-example_ci.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-example_ci.release.xcconfig"; path = "Target Support Files/Pods-example_ci/Pods-example_ci.release.xcconfig"; sourceTree = "<group>"; };
 		CC17D3301D60A24300267B0C /* NativeModule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NativeModule.h; path = example/NativeModule.h; sourceTree = "<group>"; };
 		CC17D3311D60A24300267B0C /* NativeModule.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = NativeModule.m; path = example/NativeModule.m; sourceTree = "<group>"; };
 		E088C8F21F01585500CC48E9 /* CalendarManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CalendarManager.h; path = example/CalendarManager.h; sourceTree = "<group>"; };
 		E088C8F31F01585500CC48E9 /* CalendarManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CalendarManager.m; path = example/CalendarManager.m; sourceTree = "<group>"; };
+		F5E33BEF8B2BE1E1D8A7E8BD /* Pods_example_ci.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_example_ci.framework; sourceTree = BUILT_PRODUCTS_DIR; };
 /* End PBXFileReference section */
 
 /* Begin PBXFrameworksBuildPhase section */
@@ -370,18 +107,8 @@
 			buildActionMask = 2147483647;
 			files = (
 				3953CC0D229AA78F005DD98C /* JavaScriptCore.framework in Frameworks */,
-				396B38541EC9DAC000A226F2 /* libRCTAnimation.a in Frameworks */,
 				39A34C791E30F3A000BEBB59 /* Detox.framework in Frameworks */,
-				146834051AC3E58100842450 /* libReact.a in Frameworks */,
-				00C302E51ABCBA2D00DB3ED1 /* libRCTActionSheet.a in Frameworks */,
-				00C302E81ABCBA2D00DB3ED1 /* libRCTImage.a in Frameworks */,
-				133E29F31AD74F7200F7D852 /* libRCTLinking.a in Frameworks */,
-				00C302E91ABCBA2D00DB3ED1 /* libRCTNetwork.a in Frameworks */,
-				139105C61AF99C1200B5F7CC /* libRCTSettings.a in Frameworks */,
-				832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */,
-				00C302EA1ABCBA2D00DB3ED1 /* libRCTVibration.a in Frameworks */,
-				139FDEF61B0652A700C62182 /* libRCTWebSocket.a in Frameworks */,
-				39A077AA1E5450FF00A53A07 /* libRCTPushNotification.a in Frameworks */,
+				918F6CF9DB3712E966CF1F7C /* Pods_example.framework in Frameworks */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -390,75 +117,13 @@
 			buildActionMask = 2147483647;
 			files = (
 				39ED92302291643E005EDB56 /* JavaScriptCore.framework in Frameworks */,
-				399B4DF01ED587120098D2AC /* libRCTAnimation.a in Frameworks */,
-				399B4DF21ED587120098D2AC /* libReact.a in Frameworks */,
-				399B4DF31ED587120098D2AC /* libRCTActionSheet.a in Frameworks */,
-				399B4DF51ED587120098D2AC /* libRCTImage.a in Frameworks */,
-				399B4DF61ED587120098D2AC /* libRCTLinking.a in Frameworks */,
-				399B4DF71ED587120098D2AC /* libRCTNetwork.a in Frameworks */,
-				399B4DF81ED587120098D2AC /* libRCTSettings.a in Frameworks */,
-				399B4DF91ED587120098D2AC /* libRCTText.a in Frameworks */,
-				399B4DFA1ED587120098D2AC /* libRCTVibration.a in Frameworks */,
-				399B4DFB1ED587120098D2AC /* libRCTWebSocket.a in Frameworks */,
-				399B4DFC1ED587120098D2AC /* libRCTPushNotification.a in Frameworks */,
+				4DCC563CBD5151B749FA166E /* Pods_example_ci.framework in Frameworks */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
 /* End PBXFrameworksBuildPhase section */
 
 /* Begin PBXGroup section */
-		00C302A81ABCB8CE00DB3ED1 /* Products */ = {
-			isa = PBXGroup;
-			children = (
-				00C302AC1ABCB8CE00DB3ED1 /* libRCTActionSheet.a */,
-			);
-			name = Products;
-			sourceTree = "<group>";
-		};
-		00C302BC1ABCB91800DB3ED1 /* Products */ = {
-			isa = PBXGroup;
-			children = (
-				00C302C01ABCB91800DB3ED1 /* libRCTImage.a */,
-				39A34C361E30ED3600BEBB59 /* libRCTImage-tvOS.a */,
-			);
-			name = Products;
-			sourceTree = "<group>";
-		};
-		00C302D41ABCB9D200DB3ED1 /* Products */ = {
-			isa = PBXGroup;
-			children = (
-				00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */,
-				39A34C3E1E30ED3600BEBB59 /* libRCTNetwork-tvOS.a */,
-			);
-			name = Products;
-			sourceTree = "<group>";
-		};
-		00C302E01ABCB9EE00DB3ED1 /* Products */ = {
-			isa = PBXGroup;
-			children = (
-				00C302E41ABCB9EE00DB3ED1 /* libRCTVibration.a */,
-			);
-			name = Products;
-			sourceTree = "<group>";
-		};
-		139105B71AF99BAD00B5F7CC /* Products */ = {
-			isa = PBXGroup;
-			children = (
-				139105C11AF99BAD00B5F7CC /* libRCTSettings.a */,
-				39A34C421E30ED3600BEBB59 /* libRCTSettings-tvOS.a */,
-			);
-			name = Products;
-			sourceTree = "<group>";
-		};
-		139FDEE71B06529A00C62182 /* Products */ = {
-			isa = PBXGroup;
-			children = (
-				139FDEF41B06529B00C62182 /* libRCTWebSocket.a */,
-				39A34C4B1E30ED3600BEBB59 /* libRCTWebSocket-tvOS.a */,
-			);
-			name = Products;
-			sourceTree = "<group>";
-		};
 		13B07FAE1A68108700A75B9A /* example */ = {
 			isa = PBXGroup;
 			children = (
@@ -477,45 +142,15 @@
 			name = example;
 			sourceTree = "<group>";
 		};
-		146834001AC3E56700842450 /* Products */ = {
-			isa = PBXGroup;
-			children = (
-				146834041AC3E56700842450 /* libReact.a */,
-				39A34C551E30ED3600BEBB59 /* libReact.a */,
-				39A34C571E30ED3600BEBB59 /* libyoga.a */,
-				39A34C591E30ED3600BEBB59 /* libyoga.a */,
-				39A34C5B1E30ED3600BEBB59 /* libcxxreact.a */,
-				39A34C5D1E30ED3600BEBB59 /* libcxxreact.a */,
-				395D2EAD218AFC67002E9C25 /* libjsinspector.a */,
-				395D2EAF218AFC67002E9C25 /* libjsinspector-tvOS.a */,
-				4644B8651F897583003223D4 /* libthird-party.a */,
-				4644B8671F897583003223D4 /* libthird-party.a */,
-				4644B8691F897583003223D4 /* libdouble-conversion.a */,
-				4644B86B1F897583003223D4 /* libdouble-conversion.a */,
-				39BD07C72361A5270031C946 /* libjsi.a */,
-				39BD07C92361A5270031C946 /* libjsiexecutor.a */,
-				39BD07CB2361A5270031C946 /* libjsi-tvOS.a */,
-				39BD07CD2361A5270031C946 /* libjsiexecutor-tvOS.a */,
-			);
-			name = Products;
-			sourceTree = "<group>";
-		};
-		396B38311EC9DAB600A226F2 /* Products */ = {
+		160A423EA1148BC845CDF95E /* Pods */ = {
 			isa = PBXGroup;
 			children = (
-				396B38391EC9DAB600A226F2 /* libRCTAnimation.a */,
-				396B383B1EC9DAB600A226F2 /* libRCTAnimation.a */,
+				AA201D8508E7536D1B2419C4 /* Pods-example.debug.xcconfig */,
+				66F0F062E8DEDED761A32E62 /* Pods-example.release.xcconfig */,
+				0FCE2B17362E305AD63D208E /* Pods-example_ci.debug.xcconfig */,
+				AC4951A69652648DAD57681D /* Pods-example_ci.release.xcconfig */,
 			);
-			name = Products;
-			sourceTree = "<group>";
-		};
-		39A077871E5450E700A53A07 /* Products */ = {
-			isa = PBXGroup;
-			children = (
-				39A077981E5450E700A53A07 /* libRCTPushNotification.a */,
-				39A0779A1E5450E700A53A07 /* libRCTPushNotification-tvOS.a */,
-			);
-			name = Products;
+			path = Pods;
 			sourceTree = "<group>";
 		};
 		39B0445C1DAED76400431EC5 /* Products */ = {
@@ -536,50 +171,14 @@
 			name = JS;
 			sourceTree = "<group>";
 		};
-		78C398B11ACF4ADC00677621 /* Products */ = {
-			isa = PBXGroup;
-			children = (
-				78C398B91ACF4ADC00677621 /* libRCTLinking.a */,
-				39A34C3A1E30ED3600BEBB59 /* libRCTLinking-tvOS.a */,
-			);
-			name = Products;
-			sourceTree = "<group>";
-		};
-		832341AE1AAA6A7D00B99B32 /* Libraries */ = {
-			isa = PBXGroup;
-			children = (
-				146833FF1AC3E56700842450 /* React.xcodeproj */,
-				396B38301EC9DAB600A226F2 /* RCTAnimation.xcodeproj */,
-				39A077861E5450E700A53A07 /* RCTPushNotification.xcodeproj */,
-				00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */,
-				00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */,
-				78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */,
-				00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */,
-				139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */,
-				832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */,
-				00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */,
-				139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */,
-			);
-			name = Libraries;
-			sourceTree = "<group>";
-		};
-		832341B11AAA6A8300B99B32 /* Products */ = {
-			isa = PBXGroup;
-			children = (
-				832341B51AAA6A8300B99B32 /* libRCTText.a */,
-				39A34C461E30ED3600BEBB59 /* libRCTText-tvOS.a */,
-			);
-			name = Products;
-			sourceTree = "<group>";
-		};
 		83CBB9F61A601CBA00E9B192 = {
 			isa = PBXGroup;
 			children = (
 				13B07FAE1A68108700A75B9A /* example */,
 				39FC9CFD202899D10033C11A /* JS */,
 				CCFA7DE41D11D22600E15EDF /* Frameworks */,
-				832341AE1AAA6A7D00B99B32 /* Libraries */,
 				83CBBA001A601CBA00E9B192 /* Products */,
+				160A423EA1148BC845CDF95E /* Pods */,
 			);
 			indentWidth = 4;
 			sourceTree = "<group>";
@@ -599,6 +198,8 @@
 			children = (
 				39ED920022916437005EDB56 /* JavaScriptCore.framework */,
 				39B0445B1DAED76400431EC5 /* Detox.xcodeproj */,
+				6151F84D0064B768E9F02CEB /* Pods_example.framework */,
+				F5E33BEF8B2BE1E1D8A7E8BD /* Pods_example_ci.framework */,
 			);
 			name = Frameworks;
 			sourceTree = "<group>";
@@ -610,11 +211,13 @@
 			isa = PBXNativeTarget;
 			buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "example" */;
 			buildPhases = (
+				117E8226415EB19636A83DA4 /* [CP] Check Pods Manifest.lock */,
 				13B07F871A680F5B00A75B9A /* Sources */,
 				13B07F8C1A680F5B00A75B9A /* Frameworks */,
 				13B07F8E1A680F5B00A75B9A /* Resources */,
 				00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */,
 				CC0F353E1D461097008BB94F /* Embed Frameworks */,
+				282FA8DBCD735B717420697A /* [CP] Embed Pods Frameworks */,
 			);
 			buildRules = (
 			);
@@ -630,11 +233,13 @@
 			isa = PBXNativeTarget;
 			buildConfigurationList = 399B4E031ED587120098D2AC /* Build configuration list for PBXNativeTarget "example_ci" */;
 			buildPhases = (
+				954B535809EF51A76B678921 /* [CP] Check Pods Manifest.lock */,
 				399B4DEB1ED587120098D2AC /* Sources */,
 				399B4DEF1ED587120098D2AC /* Frameworks */,
 				399B4DFD1ED587120098D2AC /* Resources */,
 				399B4E001ED587120098D2AC /* Bundle React Native code and images */,
 				399B4E011ED587120098D2AC /* Embed Frameworks */,
+				5C71CCB02684520AC0CDE3B1 /* [CP] Embed Pods Frameworks */,
 			);
 			buildRules = (
 			);
@@ -671,50 +276,6 @@
 					ProductGroup = 39B0445C1DAED76400431EC5 /* Products */;
 					ProjectRef = 39B0445B1DAED76400431EC5 /* Detox.xcodeproj */;
 				},
-				{
-					ProductGroup = 00C302A81ABCB8CE00DB3ED1 /* Products */;
-					ProjectRef = 00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */;
-				},
-				{
-					ProductGroup = 396B38311EC9DAB600A226F2 /* Products */;
-					ProjectRef = 396B38301EC9DAB600A226F2 /* RCTAnimation.xcodeproj */;
-				},
-				{
-					ProductGroup = 00C302BC1ABCB91800DB3ED1 /* Products */;
-					ProjectRef = 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */;
-				},
-				{
-					ProductGroup = 78C398B11ACF4ADC00677621 /* Products */;
-					ProjectRef = 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */;
-				},
-				{
-					ProductGroup = 00C302D41ABCB9D200DB3ED1 /* Products */;
-					ProjectRef = 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */;
-				},
-				{
-					ProductGroup = 39A077871E5450E700A53A07 /* Products */;
-					ProjectRef = 39A077861E5450E700A53A07 /* RCTPushNotification.xcodeproj */;
-				},
-				{
-					ProductGroup = 139105B71AF99BAD00B5F7CC /* Products */;
-					ProjectRef = 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */;
-				},
-				{
-					ProductGroup = 832341B11AAA6A8300B99B32 /* Products */;
-					ProjectRef = 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */;
-				},
-				{
-					ProductGroup = 00C302E01ABCB9EE00DB3ED1 /* Products */;
-					ProjectRef = 00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */;
-				},
-				{
-					ProductGroup = 139FDEE71B06529A00C62182 /* Products */;
-					ProjectRef = 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */;
-				},
-				{
-					ProductGroup = 146834001AC3E56700842450 /* Products */;
-					ProjectRef = 146833FF1AC3E56700842450 /* React.xcodeproj */;
-				},
 			);
 			projectRoot = "";
 			targets = (
@@ -725,83 +286,6 @@
 /* End PBXProject section */
 
 /* Begin PBXReferenceProxy section */
-		00C302AC1ABCB8CE00DB3ED1 /* libRCTActionSheet.a */ = {
-			isa = PBXReferenceProxy;
-			fileType = archive.ar;
-			path = libRCTActionSheet.a;
-			remoteRef = 00C302AB1ABCB8CE00DB3ED1 /* PBXContainerItemProxy */;
-			sourceTree = BUILT_PRODUCTS_DIR;
-		};
-		00C302C01ABCB91800DB3ED1 /* libRCTImage.a */ = {
-			isa = PBXReferenceProxy;
-			fileType = archive.ar;
-			path = libRCTImage.a;
-			remoteRef = 00C302BF1ABCB91800DB3ED1 /* PBXContainerItemProxy */;
-			sourceTree = BUILT_PRODUCTS_DIR;
-		};
-		00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */ = {
-			isa = PBXReferenceProxy;
-			fileType = archive.ar;
-			path = libRCTNetwork.a;
-			remoteRef = 00C302DB1ABCB9D200DB3ED1 /* PBXContainerItemProxy */;
-			sourceTree = BUILT_PRODUCTS_DIR;
-		};
-		00C302E41ABCB9EE00DB3ED1 /* libRCTVibration.a */ = {
-			isa = PBXReferenceProxy;
-			fileType = archive.ar;
-			path = libRCTVibration.a;
-			remoteRef = 00C302E31ABCB9EE00DB3ED1 /* PBXContainerItemProxy */;
-			sourceTree = BUILT_PRODUCTS_DIR;
-		};
-		139105C11AF99BAD00B5F7CC /* libRCTSettings.a */ = {
-			isa = PBXReferenceProxy;
-			fileType = archive.ar;
-			path = libRCTSettings.a;
-			remoteRef = 139105C01AF99BAD00B5F7CC /* PBXContainerItemProxy */;
-			sourceTree = BUILT_PRODUCTS_DIR;
-		};
-		139FDEF41B06529B00C62182 /* libRCTWebSocket.a */ = {
-			isa = PBXReferenceProxy;
-			fileType = archive.ar;
-			path = libRCTWebSocket.a;
-			remoteRef = 139FDEF31B06529B00C62182 /* PBXContainerItemProxy */;
-			sourceTree = BUILT_PRODUCTS_DIR;
-		};
-		146834041AC3E56700842450 /* libReact.a */ = {
-			isa = PBXReferenceProxy;
-			fileType = archive.ar;
-			path = libReact.a;
-			remoteRef = 146834031AC3E56700842450 /* PBXContainerItemProxy */;
-			sourceTree = BUILT_PRODUCTS_DIR;
-		};
-		395D2EAD218AFC67002E9C25 /* libjsinspector.a */ = {
-			isa = PBXReferenceProxy;
-			fileType = archive.ar;
-			path = libjsinspector.a;
-			remoteRef = 395D2EAC218AFC67002E9C25 /* PBXContainerItemProxy */;
-			sourceTree = BUILT_PRODUCTS_DIR;
-		};
-		395D2EAF218AFC67002E9C25 /* libjsinspector-tvOS.a */ = {
-			isa = PBXReferenceProxy;
-			fileType = archive.ar;
-			path = "libjsinspector-tvOS.a";
-			remoteRef = 395D2EAE218AFC67002E9C25 /* PBXContainerItemProxy */;
-			sourceTree = BUILT_PRODUCTS_DIR;
-		};
-		396B38391EC9DAB600A226F2 /* libRCTAnimation.a */ = {
-			isa = PBXReferenceProxy;
-			fileType = archive.ar;
-			path = libRCTAnimation.a;
-			remoteRef = 396B38381EC9DAB600A226F2 /* PBXContainerItemProxy */;
-			sourceTree = BUILT_PRODUCTS_DIR;
-		};
-		396B383B1EC9DAB600A226F2 /* libRCTAnimation.a */ = {
-			isa = PBXReferenceProxy;
-			fileType = archive.ar;
-			path = libRCTAnimation.a;
-			remoteRef = 396B383A1EC9DAB600A226F2 /* PBXContainerItemProxy */;
-			sourceTree = BUILT_PRODUCTS_DIR;
-		};
 		39A0778C1E5450E700A53A07 /* DetoxUserNotificationTests.xctest */ = {
 			isa = PBXReferenceProxy;
 			fileType = wrapper.cfbundle;
@@ -809,97 +293,6 @@
 			remoteRef = 39A0778B1E5450E700A53A07 /* PBXContainerItemProxy */;
 			sourceTree = BUILT_PRODUCTS_DIR;
 		};
-		39A077981E5450E700A53A07 /* libRCTPushNotification.a */ = {
-			isa = PBXReferenceProxy;
-			fileType = archive.ar;
-			path = libRCTPushNotification.a;
-			remoteRef = 39A077971E5450E700A53A07 /* PBXContainerItemProxy */;
-			sourceTree = BUILT_PRODUCTS_DIR;
-		};
-		39A0779A1E5450E700A53A07 /* libRCTPushNotification-tvOS.a */ = {
-			isa = PBXReferenceProxy;
-			fileType = archive.ar;
-			path = "libRCTPushNotification-tvOS.a";
-			remoteRef = 39A077991E5450E700A53A07 /* PBXContainerItemProxy */;
-			sourceTree = BUILT_PRODUCTS_DIR;
-		};
-		39A34C361E30ED3600BEBB59 /* libRCTImage-tvOS.a */ = {
-			isa = PBXReferenceProxy;
-			fileType = archive.ar;
-			path = "libRCTImage-tvOS.a";
-			remoteRef = 39A34C351E30ED3600BEBB59 /* PBXContainerItemProxy */;
-			sourceTree = BUILT_PRODUCTS_DIR;
-		};
-		39A34C3A1E30ED3600BEBB59 /* libRCTLinking-tvOS.a */ = {
-			isa = PBXReferenceProxy;
-			fileType = archive.ar;
-			path = "libRCTLinking-tvOS.a";
-			remoteRef = 39A34C391E30ED3600BEBB59 /* PBXContainerItemProxy */;
-			sourceTree = BUILT_PRODUCTS_DIR;
-		};
-		39A34C3E1E30ED3600BEBB59 /* libRCTNetwork-tvOS.a */ = {
-			isa = PBXReferenceProxy;
-			fileType = archive.ar;
-			path = "libRCTNetwork-tvOS.a";
-			remoteRef = 39A34C3D1E30ED3600BEBB59 /* PBXContainerItemProxy */;
-			sourceTree = BUILT_PRODUCTS_DIR;
-		};
-		39A34C421E30ED3600BEBB59 /* libRCTSettings-tvOS.a */ = {
-			isa = PBXReferenceProxy;
-			fileType = archive.ar;
-			path = "libRCTSettings-tvOS.a";
-			remoteRef = 39A34C411E30ED3600BEBB59 /* PBXContainerItemProxy */;
-			sourceTree = BUILT_PRODUCTS_DIR;
-		};
-		39A34C461E30ED3600BEBB59 /* libRCTText-tvOS.a */ = {
-			isa = PBXReferenceProxy;
-			fileType = archive.ar;
-			path = "libRCTText-tvOS.a";
-			remoteRef = 39A34C451E30ED3600BEBB59 /* PBXContainerItemProxy */;
-			sourceTree = BUILT_PRODUCTS_DIR;
-		};
-		39A34C4B1E30ED3600BEBB59 /* libRCTWebSocket-tvOS.a */ = {
-			isa = PBXReferenceProxy;
-			fileType = archive.ar;
-			path = "libRCTWebSocket-tvOS.a";
-			remoteRef = 39A34C4A1E30ED3600BEBB59 /* PBXContainerItemProxy */;
-			sourceTree = BUILT_PRODUCTS_DIR;
-		};
-		39A34C551E30ED3600BEBB59 /* libReact.a */ = {
-			isa = PBXReferenceProxy;
-			fileType = archive.ar;
-			path = libReact.a;
-			remoteRef = 39A34C541E30ED3600BEBB59 /* PBXContainerItemProxy */;
-			sourceTree = BUILT_PRODUCTS_DIR;
-		};
-		39A34C571E30ED3600BEBB59 /* libyoga.a */ = {
-			isa = PBXReferenceProxy;
-			fileType = archive.ar;
-			path = libyoga.a;
-			remoteRef = 39A34C561E30ED3600BEBB59 /* PBXContainerItemProxy */;
-			sourceTree = BUILT_PRODUCTS_DIR;
-		};
-		39A34C591E30ED3600BEBB59 /* libyoga.a */ = {
-			isa = PBXReferenceProxy;
-			fileType = archive.ar;
-			path = libyoga.a;
-			remoteRef = 39A34C581E30ED3600BEBB59 /* PBXContainerItemProxy */;
-			sourceTree = BUILT_PRODUCTS_DIR;
-		};
-		39A34C5B1E30ED3600BEBB59 /* libcxxreact.a */ = {
-			isa = PBXReferenceProxy;
-			fileType = archive.ar;
-			path = libcxxreact.a;
-			remoteRef = 39A34C5A1E30ED3600BEBB59 /* PBXContainerItemProxy */;
-			sourceTree = BUILT_PRODUCTS_DIR;
-		};
-		39A34C5D1E30ED3600BEBB59 /* libcxxreact.a */ = {
-			isa = PBXReferenceProxy;
-			fileType = archive.ar;
-			path = libcxxreact.a;
-			remoteRef = 39A34C5C1E30ED3600BEBB59 /* PBXContainerItemProxy */;
-			sourceTree = BUILT_PRODUCTS_DIR;
-		};
 		39B044621DAED76400431EC5 /* Detox.framework */ = {
 			isa = PBXReferenceProxy;
 			fileType = wrapper.framework;
@@ -907,76 +300,6 @@
 			remoteRef = 39B044611DAED76400431EC5 /* PBXContainerItemProxy */;
 			sourceTree = BUILT_PRODUCTS_DIR;
 		};
-		39BD07C72361A5270031C946 /* libjsi.a */ = {
-			isa = PBXReferenceProxy;
-			fileType = archive.ar;
-			path = libjsi.a;
-			remoteRef = 39BD07C62361A5270031C946 /* PBXContainerItemProxy */;
-			sourceTree = BUILT_PRODUCTS_DIR;
-		};
-		39BD07C92361A5270031C946 /* libjsiexecutor.a */ = {
-			isa = PBXReferenceProxy;
-			fileType = archive.ar;
-			path = libjsiexecutor.a;
-			remoteRef = 39BD07C82361A5270031C946 /* PBXContainerItemProxy */;
-			sourceTree = BUILT_PRODUCTS_DIR;
-		};
-		39BD07CB2361A5270031C946 /* libjsi-tvOS.a */ = {
-			isa = PBXReferenceProxy;
-			fileType = archive.ar;
-			path = "libjsi-tvOS.a";
-			remoteRef = 39BD07CA2361A5270031C946 /* PBXContainerItemProxy */;
-			sourceTree = BUILT_PRODUCTS_DIR;
-		};
-		39BD07CD2361A5270031C946 /* libjsiexecutor-tvOS.a */ = {
-			isa = PBXReferenceProxy;
-			fileType = archive.ar;
-			path = "libjsiexecutor-tvOS.a";
-			remoteRef = 39BD07CC2361A5270031C946 /* PBXContainerItemProxy */;
-			sourceTree = BUILT_PRODUCTS_DIR;
-		};
-		4644B8651F897583003223D4 /* libthird-party.a */ = {
-			isa = PBXReferenceProxy;
-			fileType = archive.ar;
-			path = "libthird-party.a";
-			remoteRef = 4644B8641F897583003223D4 /* PBXContainerItemProxy */;
-			sourceTree = BUILT_PRODUCTS_DIR;
-		};
-		4644B8671F897583003223D4 /* libthird-party.a */ = {
-			isa = PBXReferenceProxy;
-			fileType = archive.ar;
-			path = "libthird-party.a";
-			remoteRef = 4644B8661F897583003223D4 /* PBXContainerItemProxy */;
-			sourceTree = BUILT_PRODUCTS_DIR;
-		};
-		4644B8691F897583003223D4 /* libdouble-conversion.a */ = {
-			isa = PBXReferenceProxy;
-			fileType = archive.ar;
-			path = "libdouble-conversion.a";
-			remoteRef = 4644B8681F897583003223D4 /* PBXContainerItemProxy */;
-			sourceTree = BUILT_PRODUCTS_DIR;
-		};
-		4644B86B1F897583003223D4 /* libdouble-conversion.a */ = {
-			isa = PBXReferenceProxy;
-			fileType = archive.ar;
-			path = "libdouble-conversion.a";
-			remoteRef = 4644B86A1F897583003223D4 /* PBXContainerItemProxy */;
-			sourceTree = BUILT_PRODUCTS_DIR;
-		};
-		78C398B91ACF4ADC00677621 /* libRCTLinking.a */ = {
-			isa = PBXReferenceProxy;
-			fileType = archive.ar;
-			path = libRCTLinking.a;
-			remoteRef = 78C398B81ACF4ADC00677621 /* PBXContainerItemProxy */;
-			sourceTree = BUILT_PRODUCTS_DIR;
-		};
-		832341B51AAA6A8300B99B32 /* libRCTText.a */ = {
-			isa = PBXReferenceProxy;
-			fileType = archive.ar;
-			path = libRCTText.a;
-			remoteRef = 832341B41AAA6A8300B99B32 /* PBXContainerItemProxy */;
-			sourceTree = BUILT_PRODUCTS_DIR;
-		};
 /* End PBXReferenceProxy section */
 
 /* Begin PBXResourcesBuildPhase section */
@@ -1015,6 +338,45 @@
 			shellPath = /bin/sh;
 			shellScript = "export NODE_BINARY=node\n../node_modules/react-native/scripts/react-native-xcode.sh";
 		};
+		117E8226415EB19636A83DA4 /* [CP] Check Pods Manifest.lock */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputFileListPaths = (
+			);
+			inputPaths = (
+				"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
+				"${PODS_ROOT}/Manifest.lock",
+			);
+			name = "[CP] Check Pods Manifest.lock";
+			outputFileListPaths = (
+			);
+			outputPaths = (
+				"$(DERIVED_FILE_DIR)/Pods-example-checkManifestLockResult.txt",
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n    # print error to STDERR\n    echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n    exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
+			showEnvVarsInLog = 0;
+		};
+		282FA8DBCD735B717420697A /* [CP] Embed Pods Frameworks */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputFileListPaths = (
+				"${PODS_ROOT}/Target Support Files/Pods-example/Pods-example-frameworks-${CONFIGURATION}-input-files.xcfilelist",
+			);
+			name = "[CP] Embed Pods Frameworks";
+			outputFileListPaths = (
+				"${PODS_ROOT}/Target Support Files/Pods-example/Pods-example-frameworks-${CONFIGURATION}-output-files.xcfilelist",
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-example/Pods-example-frameworks.sh\"\n";
+			showEnvVarsInLog = 0;
+		};
 		399B4E001ED587120098D2AC /* Bundle React Native code and images */ = {
 			isa = PBXShellScriptBuildPhase;
 			buildActionMask = 2147483647;
@@ -1029,6 +391,45 @@
 			shellPath = /bin/sh;
 			shellScript = "../node_modules/react-native/scripts/react-native-xcode.sh\n";
 		};
+		5C71CCB02684520AC0CDE3B1 /* [CP] Embed Pods Frameworks */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputFileListPaths = (
+				"${PODS_ROOT}/Target Support Files/Pods-example_ci/Pods-example_ci-frameworks-${CONFIGURATION}-input-files.xcfilelist",
+			);
+			name = "[CP] Embed Pods Frameworks";
+			outputFileListPaths = (
+				"${PODS_ROOT}/Target Support Files/Pods-example_ci/Pods-example_ci-frameworks-${CONFIGURATION}-output-files.xcfilelist",
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-example_ci/Pods-example_ci-frameworks.sh\"\n";
+			showEnvVarsInLog = 0;
+		};
+		954B535809EF51A76B678921 /* [CP] Check Pods Manifest.lock */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputFileListPaths = (
+			);
+			inputPaths = (
+				"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
+				"${PODS_ROOT}/Manifest.lock",
+			);
+			name = "[CP] Check Pods Manifest.lock";
+			outputFileListPaths = (
+			);
+			outputPaths = (
+				"$(DERIVED_FILE_DIR)/Pods-example_ci-checkManifestLockResult.txt",
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n    # print error to STDERR\n    echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n    exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
+			showEnvVarsInLog = 0;
+		};
 /* End PBXShellScriptBuildPhase section */
 
 /* Begin PBXSourcesBuildPhase section */
@@ -1079,6 +480,7 @@
 /* Begin XCBuildConfiguration section */
 		13B07F941A680F5B00A75B9A /* Debug */ = {
 			isa = XCBuildConfiguration;
+			baseConfigurationReference = AA201D8508E7536D1B2419C4 /* Pods-example.debug.xcconfig */;
 			buildSettings = {
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
 				DEAD_CODE_STRIPPING = NO;
@@ -1094,6 +496,7 @@
 					"@executable_path/Frameworks",
 				);
 				OTHER_LDFLAGS = (
+					"$(inherited)",
 					"-ObjC",
 					"-lc++",
 				);
@@ -1105,10 +508,14 @@
 		};
 		13B07F951A680F5B00A75B9A /* Release */ = {
 			isa = XCBuildConfiguration;
+			baseConfigurationReference = 66F0F062E8DEDED761A32E62 /* Pods-example.release.xcconfig */;
 			buildSettings = {
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
 				DEVELOPMENT_TEAM = "";
-				GCC_PREPROCESSOR_DEFINITIONS = "EXTERNAL_LOGGER=1";
+				GCC_PREPROCESSOR_DEFINITIONS = (
+					"EXTERNAL_LOGGER=1",
+					"$(inherited)",
+				);
 				INFOPLIST_FILE = example/Info.plist;
 				IPHONEOS_DEPLOYMENT_TARGET = 9.0;
 				LD_RUNPATH_SEARCH_PATHS = (
@@ -1116,6 +523,7 @@
 					"@executable_path/Frameworks",
 				);
 				OTHER_LDFLAGS = (
+					"$(inherited)",
 					"-ObjC",
 					"-lc++",
 				);
@@ -1127,6 +535,7 @@
 		};
 		399B4E041ED587120098D2AC /* Debug */ = {
 			isa = XCBuildConfiguration;
+			baseConfigurationReference = 0FCE2B17362E305AD63D208E /* Pods-example_ci.debug.xcconfig */;
 			buildSettings = {
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
 				DEAD_CODE_STRIPPING = NO;
@@ -1141,6 +550,7 @@
 					"-ObjC",
 					"-lc++",
 					"-Wl,-U,___dtx_send_external_log",
+					"$(inherited)",
 				);
 				PRODUCT_BUNDLE_IDENTIFIER = "com.wix.detox-example";
 				PRODUCT_NAME = example;
@@ -1150,6 +560,7 @@
 		};
 		399B4E051ED587120098D2AC /* Release */ = {
 			isa = XCBuildConfiguration;
+			baseConfigurationReference = AC4951A69652648DAD57681D /* Pods-example_ci.release.xcconfig */;
 			buildSettings = {
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
 				DEVELOPMENT_TEAM = "";
@@ -1163,6 +574,7 @@
 					"-ObjC",
 					"-lc++",
 					"-Wl,-U,___dtx_send_external_log",
+					"$(inherited)",
 				);
 				PRODUCT_BUNDLE_IDENTIFIER = "com.wix.detox-example";
 				PRODUCT_NAME = example;
diff --git a/detox/test/ios/example.xcworkspace/contents.xcworkspacedata b/detox/test/ios/example.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 000000000..7f5c3aab5
--- /dev/null
+++ b/detox/test/ios/example.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Workspace
+   version = "1.0">
+   <FileRef
+      location = "group:example.xcodeproj">
+   </FileRef>
+   <FileRef
+      location = "group:Pods/Pods.xcodeproj">
+   </FileRef>
+</Workspace>
diff --git a/detox/test/package.json b/detox/test/package.json
index a586412ed..751418129 100644
--- a/detox/test/package.json
+++ b/detox/test/package.json
@@ -1,6 +1,6 @@
 {
   "name": "detox-test",
-  "version": "14.9.1",
+  "version": "14.9.2",
   "private": true,
   "engines": {
     "node": ">=8.3.0"
@@ -26,12 +26,12 @@
   },
   "dependencies": {
     "moment": "^2.24.0",
-    "react": "16.8.x",
-    "react-native": "0.60.x"
+    "react": "16.9.0",
+    "react-native": "0.61.4"
   },
   "devDependencies": {
     "@babel/core": "^7.4.5",
-    "detox": "^14.9.1",
+    "detox": "^14.9.2",
     "express": "^4.15.3",
     "jest": "24.9.x",
     "jest-circus": "24.9.x",
@@ -49,7 +49,7 @@
     "configurations": {
       "ios.sim.debug": {
         "binaryPath": "ios/build/Build/Products/Debug-iphonesimulator/example.app",
-        "build": "set -o pipefail && xcodebuild -project ios/example.xcodeproj -UseNewBuildSystem=NO -scheme example_ci -configuration Debug -sdk iphonesimulator -derivedDataPath ios/build",
+        "build": "set -o pipefail && xcodebuild -workspace ios/example.xcworkspace -UseNewBuildSystem=NO -scheme example_ci -configuration Debug -sdk iphonesimulator -derivedDataPath ios/build",
         "type": "ios.simulator",
         "device": {
           "type": "iPhone 11 Pro"
@@ -57,7 +57,7 @@
       },
       "ios.sim.release": {
         "binaryPath": "ios/build/Build/Products/Release-iphonesimulator/example.app",
-        "build": "set -o pipefail && export CODE_SIGNING_REQUIRED=NO && export RCT_NO_LAUNCH_PACKAGER=true && xcodebuild -project ios/example.xcodeproj  -UseNewBuildSystem=NO -scheme example_ci -configuration Release -sdk iphonesimulator -derivedDataPath ios/build",
+        "build": "set -o pipefail && export CODE_SIGNING_REQUIRED=NO && export RCT_NO_LAUNCH_PACKAGER=true && xcodebuild -workspace ios/example.xcworkspace -UseNewBuildSystem=NO -scheme example_ci -configuration Release -sdk iphonesimulator -derivedDataPath ios/build",
         "type": "ios.simulator",
         "device": {
           "type": "iPhone 11 Pro"
diff --git a/detox/test/src/Screens/LaunchArgsScreen.js b/detox/test/src/Screens/LaunchArgsScreen.js
index d6b7efaef..ebf6d5de7 100644
--- a/detox/test/src/Screens/LaunchArgsScreen.js
+++ b/detox/test/src/Screens/LaunchArgsScreen.js
@@ -18,7 +18,7 @@ export default class LaunchArgsScreen extends Component {
     }
   }
 
-  async componentWillMount() {
+  async componentDidMount() {
     const launchArgs = await NativeModule.getLaunchArguments();
     this.setState({
       launchArgs,
diff --git a/detox/test/src/Screens/ShakeScreen.js b/detox/test/src/Screens/ShakeScreen.js
index 8e01c1e33..0f13366e0 100644
--- a/detox/test/src/Screens/ShakeScreen.js
+++ b/detox/test/src/Screens/ShakeScreen.js
@@ -21,6 +21,10 @@ export default class ShakeScreen extends Component {
       greeting: "Shake it, baby"
     };
     this.subscription = undefined;
+    this.subscription = shakeEventEmitter.addListener('ShakeEvent', () => {
+      console.log("Shake!!!");
+      this.setState({ greeting: "Shaken, not stirred" });
+    });
   }
 
   render() {
@@ -33,13 +37,6 @@ export default class ShakeScreen extends Component {
     );
   }
 
-  componentWillMount() {
-    this.subscription = shakeEventEmitter.addListener('ShakeEvent', () => {
-      console.log("Shake!!!");
-      this.setState({ greeting: "Shaken, not stirred" });
-    });
-  }
-
   componentWillUnmount() {
     console.log("Unsubscribing");
     this.subscription.remove();
diff --git a/detox/test/src/app.js b/detox/test/src/app.js
index a01ede131..2fe46c00c 100644
--- a/detox/test/src/app.js
+++ b/detox/test/src/app.js
@@ -22,11 +22,7 @@ class example extends Component {
       notification: undefined
     };
 
-    // TODO this is a hack for RN 0.60: Android warns of the deprecation (yellow-box), while iOS can't live
-    //   without this method (native error).
-    if (!isAndroid) {
-      this.componentWillMount = () => {};
-    }
+    Linking.addEventListener('url', (params) => this._handleOpenURL(params));
   }
 
   renderButton(title, onPressCallback) {
diff --git a/examples/demo-react-native-jest/e2e/init-circus.js b/examples/demo-react-native-jest/e2e/init-circus.js
index 05bc48df3..b22a8a858 100644
--- a/examples/demo-react-native-jest/e2e/init-circus.js
+++ b/examples/demo-react-native-jest/e2e/init-circus.js
@@ -9,11 +9,11 @@ detoxCircus.getEnv().addEventsListener(assignReporter);
 detoxCircus.getEnv().addEventsListener(specReporter);
 
 // Set the default timeout
-jest.setTimeout(300000);
+jest.setTimeout(90000);
 
 beforeAll(async () => {
   await detox.init(config);
-});
+}, 300000);
 
 beforeEach(async () => {
   await adapter.beforeEach();
diff --git a/examples/demo-react-native-jest/e2e/init.js b/examples/demo-react-native-jest/e2e/init.js
index 31fad763c..1d63d35bb 100644
--- a/examples/demo-react-native-jest/e2e/init.js
+++ b/examples/demo-react-native-jest/e2e/init.js
@@ -4,9 +4,6 @@ const adapter = require('detox/runners/jest/adapter');
 const specReporter = require('detox/runners/jest/specReporter');
 const assignReporter = require('detox/runners/jest/assignReporter');
 
-// Set the default timeout
-jest.setTimeout(300000);
-
 jasmine.getEnv().addReporter(adapter);
 
 // This takes care of generating status logs on a per-spec basis. By default, jest only reports at file-level.
@@ -17,9 +14,12 @@ jasmine.getEnv().addReporter(specReporter);
 // This is strictly optional.
 jasmine.getEnv().addReporter(assignReporter);
 
+// Set the default timeout
+jest.setTimeout(90000);
+
 beforeAll(async () => {
   await detox.init(config);
-});
+}, 300000);
 
 beforeEach(async () => {
   await adapter.beforeEach();