docs: rework introduction

This commit is contained in:
Yaroslav Serhieiev
2022-09-15 21:04:36 +03:00
parent 26f79945bc
commit 20724c1be7
82 changed files with 2595 additions and 2456 deletions
+4
View File
@@ -22,5 +22,9 @@ tab_width = 4
indent_size = 2
tab_width = 2
[{*.md,*.mdx}]
indent_size = 2
tab_width = 2
[{*.har,*.jsb2,*.jsb3,*.json,.babelrc,.eslintrc,.prettierrc,.stylelintrc,bowerrc,jest.config}]
indent_size = 2
+1 -1
View File
@@ -66,7 +66,7 @@ Detox is built from the ground up to support React Native projects as well as pu
The following React Native versions have been tested:
| iOS | Android |
|-----------------|---------------------------------------------------------------------------------------------------------------------------|
| --------------- | ------------------------------------------------------------------------------------------------------------------------- |
| 0.66.x - 0.69.5 | 0.66.x - 0.69.5 -<br/>Visibility edge-case: see this [RN issue](https://github.com/facebook/react-native/issues/23870) \* |
Future versions are most likely supported, but have not been tested yet. Please open issues if you find specific issues with newer React Native versions.
-537
View File
@@ -1,537 +0,0 @@
---
id: configuration
slug: api/configuration
title: Configuration Options
sidebar_label: Configuration Options
---
## Configuration Options
### Configuration File
In order for Detox to know what device & app to use (and a lot more, actually), it needs some configuration to be statically available in a configuration file. It supports both standalone configuration files, and a configuration bundling inside the project’s `package.json`.
In essence, Detox scans for the configuration to use, through multiple files. It starts from the current working directory, and runs over the following options, in this order:
1. `.detoxrc.js`
1. `.detoxrc.json`
1. `.detoxrc`
1. `detox.config.js`
1. `detox.config.json`
1. `package.json` (`"detox"` section)
Options 1-5 allow for a standalone Detox configuration in either a `json` format or using JavaScript syntax.
Option 6 means the configuration is available in `json` format inside the project’s `package.json`, which is more suitable if you like having all of your project’s configurations in one place.
Please find the [Detox example app](https://github.com/wix/Detox/blob/master/examples/demo-react-native/detox.config.js) as a working reference. Also, look at
[the typings file](https://github.com/wix/Detox/blob/master/detox/index.d.ts) provided by Detox.
#### Extending configurations
Since Detox [18.9.0](https://github.com/wix/Detox/releases/tag/18.9.0), you can also define base Detox configurations,
distribute them as `npm` modules for reuse across multiple projects, e.g.:
```js
{
"extends": "@my-org/detox-preset",
"runnerConfig": "e2e/jest.config.some-override.js"
}
```
Please note that `extends` has to be a valid Node module path. Relative module paths will be resolved relatively
to the Detox config file which contains that specific `extends` property, e.g.:
```js
// given: ~/Projects/my-project/.detoxrc.json
{ extends: "./e2e/detox-base-config" }
// goes to: ~/Projects/my-project/e2e/detox-base-config.js
{ extends: "./configs/base" }
// then goes to: ~/Projects/my-project/e2e/configs/base/index.js
// and so on...
```
#### Individual Configurations
> NOTE: The configuration format has been significantly updated since [18.3.1](https://github.com/wix/Detox/blob/18.3.1/docs/APIRef.Configuration.md) in a backward-compatible way.
> Click [here](https://github.com/wix/Detox/blob/18.3.1/docs/APIRef.Configuration.md) to the reference on the former configuration format.
`configurations` holds all the device/app-oriented configurations. To select a specific configuration when running Detox in command-line (i.e. `detox build`, `detox test`), use the `--configuration` argument.
Note: If there is only one configuration in `configurations`, Detox will default to it.
| Configuration Params | Details |
| -------------------- | -------------------------------------------------------------------------------------------------------------------- |
| `device` | Device config (object) or an alias pointing to an already defined device in `"devices"` dictionary (see below). |
| `app` | App config (object) or an alias pointing to an already defined application in `"apps"` dictionary (see below). |
| `apps` | Same as the `app`, but that is an array form used for multi-app testing. Mutually exclusive with the `app` property. |
| `artifacts` | Overrides to the artifacts config. See [Artifacts guide](#artifacts-configuration). |
| `behavior` | Overrides to the behavior config. See [Behavior guide](#behavior-configuration). |
| `session` | Overrides to the session config. See [Session guide](#server-configuration). |
| | |
| `runnerConfig` | Path to the test runner config. Default value: `e2e/config.json`. |
| `specs` | A default glob pattern for a test runner to use when no test files are specified, e.g.: `e2e/**/*.test.js` |
**Example:**
```js
{
// ...
"detox": {
// ...
"devices": {
// ... see below ...
},
"apps": {
// ... see below ...
},
"session": {
// ... see below ...
},
"configurations": {
"ios.sim.debug": {
"device": "simulator",
"app": "ios.debug"
},
"android.emu.release": {
"device": "emulator",
"app": "android.release"
},
"android.att.release": {
"device": "android.attached",
"app": "android.release"
},
"android.genymotion.release": {
"device": "android.genycloud",
"app": "android.release"
}
}
}
}
```
#### Device configurations
The format of Detox config allows you to define inside it multiple device configs in a key-value manner, i.e.:
```js
{
"devices": {
"simulator": {
"type": "ios.simulator",
"device": {
// one of these or a combination of them
"id": "D53474CF-7DD1-4673-8517-E75DAD6C34D6",
"type": "iPhone 11 Pro",
"name": "MySim",
"os": "iOS 13.0"
}
},
"emulator": {
"type": "android.emulator",
"device": {
"avdName": "Pixel_2_API_29"
},
"utilBinaryPaths": [
"optional-property-with/path/to/test-butler-or-anything-else.apk"
]
},
"android.attached": {
"type": "android.attached",
"device": {
"adbName": "YOGAA1BBB412"
}
},
"android.genycloud": {
"type": "android.genycloud",
"device": {
"recipeUUID": "11111111-2222-3333-4444-555555555555"
// or recipeName: "MyRecipeName",
}
}
},
"apps": {
// ... see below ...
},
"configurations": {
// ... see above ...
}
}
```
A device config can have the following params:
| Configuration Params | Details |
| -------------------- |-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `type` | _**Required.** String Literal_. Mandatory property to discern device types: `ios.simulator`, `android.emulator`, `android.attached`, `android.genycloud` etc. |
| `device` | _**Required.** Object._ Device query, e.g. `{ "byType": "iPhone 11 Pro" }` for iOS simulator, `{ "avdName": "Pixel_2_API_29" }` for Android emulator or `{ "adbName": "<pattern>" }` for attached Android device with name matching the regex. |
| `bootArgs` | _Optional. String. Supported by `ios.simulator` and `android.emulator` only._ <br/> Supply an extra _String_ of arguments to `xcrun simctl boot ...` or `emulator -verbose ... @AVD_Name`. |
| `forceAdbInstall` | _Optional. Boolean. Supported for Android devices only._ <br/> A _Boolean_ value, `false` by default. When set to `true`, it tells `device.installApp()` to use `adb install`. Otherwise, it would use the combination of `adb push <app.apk>` and `adb shell pm install`. |
| `utilBinaryPaths` | _Optional. Array of strings. Supported for Android devices only._ <br/> An array of relative paths of _utility_ app (APK) binary-files to preinstall on the tested devices - once before the test execution begins.<br/>**Note**: these are not affected by various install-lifecycle events, such as launching an app with `device.launchApp({delete: true})`, which reinstalls the app. A good example of why this might come in handy is [Test Butler](https://github.com/linkedin/test-butler). |
| `gpuMode` | _Optional. String Literal (<code>auto</code>). Supported by `android.emulator` only._ <br/> A fixed **string** , which tells [in which GPU mode](https://developer.android.com/studio/run/emulator-acceleration#command-gpu) the emulator should be booted. |
| `headless` | _Optional. Boolean._ `false` by default. When set to `true`, it tells Detox to boot an Android emulator with `-no-window` option, or to not open the iOS Simulator app when running with Android or iOS respectively. |
| `readonly` | _Optional. Boolean. Supported by `android.emulator` only._ <br/> `false` by default. When set to `true`, it forces Detox to boot even a single emulator with `-read-only` option.<br/>**Note**: when used with multiple workers, this setting has no effect — emulators will be booted always with `-read-only`. |
Also, in the Detox `configurations` you can use the device configs as-is, without aliasing:
```js
{
"configurations": {
"ios.sim.debug": {
"device": {
"type": "ios.simulator",
"device": {
"type": "iPhone 12 Pro"
}
},
"app": "alias-to-app"
// ...
}
}
}
```
#### Apps configurations
The format of Detox config allows you to define inside it multiple app configs in a key-value manner, i.e.:
```js
{
"devices": {
// ... see above ...
},
"apps": {
"ios.debug": {
"type": "ios.app",
"binaryPath": "ios/build/Build/Products/Debug-iphonesimulator/example.app",
"build": "xcodebuild -project ios/example.xcodeproj -scheme example -configuration Debug -sdk iphonesimulator -derivedDataPath ios/build"
},
"android.release": {
"type": "android.apk",
"binaryPath": "path/to/myApp.apk",
"build": "..."
}
},
"configurations": {
// ... see above ...
}
}
```
An app config can have the following params:
| Configuration Params | Details |
| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `type` | Mandatory property to discern app types: `ios.app`, `android.apk`. |
| `name` | Use only when working with multiple apps within the same configuration. See an example below. |
| `binaryPath` | Relative path to the ipa/app/apk due to be tested (make sure you build the app in a project relative path) |
| `build` | **\[optional]** Build command (normally an `xcodebuild` command you use to build your app), which can be called later using Detox CLI tool as a convenience. |
| `testBinaryPath` | (optional, Android only): relative path to the test app (apk) |
| `launchArgs` | **\[optional]** An object specifying arguments (key-values pairs) to pass through into the app, upon launching on the device. For more info, refer to the dedicated [launch-arguments guide](APIRef.LaunchArgs.md). |
To work with multiple apps within the same configuration you should be giving each app its name, e.g.:
```js
{
"apps": {
"driver.ios.release": {
"type": "ios.app",
"name": "driver",
"binaryPath": "path/to/driver.app"
},
"passenger.ios.release": {
"type": "ios.app",
"name": "passenger",
"binaryPath": "path/to/passenger.app"
}
},
"configurations": {
"ios.release": {
"device": "simulator",
"apps": ["driver", "passenger"]
}
}
}
```
After that, you can change the current app in your tests via [device API](APIRef.DeviceObjectAPI.md):
```js
await device.selectApp('driver');
await device.launchApp();
// ... run tests ...
await device.selectApp('passenger');
await device.launchApp();
// ... run tests ...
```
Similar to device configs, any app config can be inlined as well:
```js
{
"configurations": {
"ios.sim.debug": {
"device": "simulator",
"app": {
"type": "ios.app",
"binaryPath": "ios/build/Build/Products/Debug-iphonesimulator/example.app",
"build": "xcodebuild -project ios/example.xcodeproj -scheme example -configuration Debug -sdk iphonesimulator -derivedDataPath ios/build"
}
}
}
}
```
#### Artifacts Configuration
See more details in [artifacts doc](APIRef.Artifacts.md).
Detox can store artifacts such as transient screenshots and device logs.
You can control artifacts collection via Detox configuration:
```js
{
"artifacts": {
"rootDir": ".artifacts",
"pathBuilder": "./config/pathbuilder.js",
"plugins": {
"instruments": {"enabled": false},
"log": {"enabled": true},
"uiHierarchy": "enabled",
"screenshot": {
"shouldTakeAutomaticSnapshots": true,
"keepOnlyFailedTestsArtifacts": true,
"takeWhen": {
"testStart": false,
"testDone": true
}
},
"video": {
"android": {
"bitRate": 4000000
},
"simulator": {
"codec": "hevc"
}
}
}
},
"configurations": {
"ios.sim.release": {
// ...
"artifacts": {
"rootDir": ".artifacts/ios",
"plugins": {
"instruments": "all"
}
}
}
}
}
```
As can be seen from the example above, in a specific configuration you may override individual properties from the default artifacts
configuration. For instance, in the example above you can see that specifically in `ios.sim.release` we turn on `instruments` plugin.
CLI arguments (e.g., `--artifacts-location`, `--record-logs`) still have the highest priority and override their counterparts from JSON.
Also, that example demonstrates that you can use strings (identical to the ones from CLI) in parallel to the object configurations for plugins.
Below you can see mappings between the string presets and the corresponding objects:
| preset | object |
| ------- | ------------------------------------------------------------ |
| none | `{ "enabled": false }` |
| all | `{ "enabled": true }` |
| failing | `{ "enabled": true, "keepOnlyFailedTestsArtifacts": true }` |
| manual | `{ "enabled": true, "shouldTakeAutomaticSnapshots": false }` |
There is also a shortcut to disable artifacts for a specific configuration:
```js
{
"configurations": {
"ios.no-artifacts": {
// ...
"artifacts": false
}
}
}
```
#### Behavior Configuration
If you need to tweak the flow of `detox.init()` or `detox.cleanup()` steps,
you have a few options to change. These are the default behavior values:
```json
{
"detox": {
"behavior": {
"init": {
"reinstallApp": true,
"exposeGlobals": true
},
"launchApp": "auto",
"cleanup": {
"shutdownDevice": false
}
}
}
}
```
The `launchApp: "auto"` setting can be changed to `"manual"` for cases when you want to debug the
native codebase when running Detox tests. Usually **you never need that**, but if you do, follow the
[Debugging Apps in Android Studio During a Test](Guide.DebuggingInAndroidStudio.md) guide to learn
more about this. When set to `manual`, it changes the default value of `reinstallApp` to `false`.
Setting `reinstallApp: false` will make the tests reuse the currently installed app on the device,
provided you have installed it beforehand explicitly or manually.
If you do not wish to leak Detox globals (`expect`, `device`, `by`, etc.) to the global
scope, you can set `"exposeGlobals": false` and destructure them respectively from the
exported Detox interface:
```js
const { by, device, expect, element } = require('detox');
```
Also, you can override the behavior in specific Detox configurations:
```js
{
"behavior": {
// ... global behavior ...
},
"configurations": {
"ios.manual": {
"behavior": {
// ... overrides ...
"launchApp": "manual"
// ... overrides ...
}
}
}
}
```
#### Server Configuration
Detox can either initialize a server using a generated configuration, or can be overridden with a manual configuration:
```json
{
"session": {
"server": "ws://localhost:8099",
"sessionId": "YourProjectSessionId"
}
}
```
When you define a session config, the Detox server won’t start automatically anymore — it is assumed that
you will be running it independently via `detox run-server` CLI command. Alternatively, you can set the
`autoStart` property to be explicitly `true`:
```diff
"session": {
+ "autoStart": true,
"server": "ws://localhost:8099",
"sessionId": "YourProjectSessionId"
```
Defining an explicit session config with `server` and `sessionId` also means you cannot use multiple workers,
since the specified port will become busy for any test worker next to the first one to occupy it.
Session can be set also per device configuration — then it takes a higher priority over the global
session config:
```json
{
"configurations": {
"ios.sim.debug": {
// ...
"session": {
"server": "ws://localhost:8099",
"sessionId": "YourProjectSessionId"
}
}
}
}
```
Also, you can specify an optional numeric `debugSynchronization` parameter
(see also `--debug-synchronization` in [`detox-cli` test section](APIRef.DetoxCLI.md#test)).
When an action/expectation takes a significant amount time, use this option to print device synchronization status.
The status will be printed if the action takes more than _\[N]_ ms to complete.
```json
{
"session": {
"debugSynchronization": 20000
}
}
```
To disable `debugSynchronization` explicitly, use `0`.
### `detox-cli`
#### Build Configuration
In your detox config (in `package.json`) paste your build command into the configuration’s `build` field.
The build command will be triggered when running `detox build`.
**This is only a convenience method, to help you manage building multiple configurations of your app and couple them to your tests. You can also choose not to use it and provide a compiled `app` by yourself.**
You can choose to build your project in any of these ways...
- If there’s only one configuration, you can simply use:
```sh
detox build
```
- To choose a specific configuration:
```sh
detox build --configuration yourConfiguration
```
- Building with `xcodebuild`:
```sh
xcodebuild -project ios/YourProject.xcodeproj -scheme YourProject -sdk iphonesimulator -derivedDataPath ios/build
```
- Building using React Native, this is the least suggested way of running your build, since it also starts a random simulator and installs the app on it.
```sh
react-native run-ios
```
> Note: remember to update the `app` path in your `package.json`.
#### Test Configuration
- If there’s only one configuration, you can simply use:
```sh
detox test ./e2e
```
where `./e2e` is the path to your Detox tests folder.
- For multiple configurations, choose your configuration by passing `--configuration` param:
```sh
detox test ./e2e --configuration yourConfiguration
```
#### Faster Test Runs with App Reuse
By default, the app is removed, reinstalled and launched before each run.
Starting fresh is critical in CI but during the development you might be able to save time between test runs and reuse the app that was previously installed in the simulator. To do so use the `reuse` flag and run your tests like this:
```sh
detox test ./e2e --reuse
```
This is especially useful with React Native development mode when making JavaScript code changes that are getting picked up by the packager (and thus no reinstall is needed). This can save up to 7 seconds per run!
You should not use this option if you made native code changes or if your app relies on local ("disk") storage.
-61
View File
@@ -1,61 +0,0 @@
---
id: detox-object-api
slug: api/detox-object-api
title: Detox Object API
sidebar_label: The `detox` Object
---
## The `detox` Object
TODO: rewrite this document
### Methods
- [`detox.traceCall()`](#detoxtracecall)
- [`detox.trace.startSection(), detox.trace.endSection()`](#detoxtracestartsection-detoxtraceendsection)
#### `detox.traceCall()`
:warning: **Beta**
Trace a subprocess of your test’s runtime such that it would leave traces inside the [Timeline artifact](APIRef.Artifacts.md#timeline-plugin), for a later inspection.
Example:
```js
it('Verify sanity things', async () => {
// Instead of this typical direct call:
// await element(by.id('sanityButton')).tap()
// Use traceCall() as a wrapper:
await detox.traceCall('Navigate to sanity', () =>
element(by.id('sanityButton')).tap());
});
```
This would have the `tap` action traced to the final artifact, so it would look something like this:
![User event](img/timeline-artifact-userEvent.png)
At the bottom right, you can see what portion of the test was spent in handling the whole navigation process: tap + screen push + screen rendering (i.e. action time, alongside Detox' inherent wait for the application to become idle).
#### `detox.trace.startSection(), detox.trace.endSection()`
:warning: **Beta**
This is similar to the `traceCall()` API, except that it gives more freedom with respect to when a section’s start and ending times are defined, so as to monitor a nontrivial flow. As a usage example:
```js
it('Verify sanity things', async () => {
try {
detox.trace.startSection('Turn off notifications');
await element(by.id('gotoNotifications')).tap();
await element(by.id('notificationsToggle')).tap();
await device.pressBack();
} finally {
detox.trace.endSection('Turn off notifications');
}
});
```
Effectively, `start` and `end` can even be called in two complete different places - such as a `before` and an `after`. But that is discouraged. In fact, **usage of `detox.traceCall()` is the recommended way of tracing things, altogether.**
-42
View File
@@ -1,42 +0,0 @@
---
id: test-lifecycle
slug: api/test-lifecycle
title: Test Lifecycle
sidebar_label: Test Lifecycle
---
## Test Lifecycle
TODO: re-write this (!!!) for Jest Circus.
### Initial Setup
...
### Before and After Each Test
...
### Teardown
...
### Repeating Setup for All Tests
A good practice for testing in general is to have decoupled tests, meaning that each test has the same starting point, and the tests can run in any order and still produce the same results. We strongly encourage either restarting your application or restart react-native (if your application is built with it).
#### Reloading React Native
```js
beforeEach(async () => {
await device.reloadReactNative();
});
```
#### Relaunching the Entire App
```js
beforeEach(async () => {
await device.launchApp({newInstance: true});
});
```
@@ -1,38 +1,38 @@
---
id: android-dev-env
slug: introduction/android-dev-env
slug: guide/android-dev-env
title: Setting Up an Android Development & Testing Environment
sidebar_label: Setting Up an Android Development & Testing Environment
---
## Setting Up an Android Development & Testing Environment
This guide provides some core practices to follow in setting up a stable, reliable environment for running automated UI tests using Android emulators (using Detox, in particular) -- be it on a personal, _local_ computer, or a powerful CI machine.
This guide provides some core practices to follow in setting up a stable, reliable environment for running automated UI tests using Android emulators (using Detox, in particular) – be it on a personal, _local_ computer, or a powerful CI machine.
Note that running automated UI tests is _not the same_ as developing Android apps. Hence, you may find yourself not 100% aligned with the recommendations here, and should consider being so.
## Java Setup
This is the most basic step in the process, as without a proper Java SDK installed, nothing Android-ish works -- at least not from command-line, which is mandatory for executing `Detox`.
This is the most basic step in the process, as without a proper Java SDK installed, nothing Android-ish works – at least not from command-line, which is mandatory for executing `Detox`.
_The bottom line is that **Android needs Java installed**. If you want to run with React Native 66 and Android 12 then it needs to be at least Java 11, otherwise you should have Java 8._
To check for your real java-executable’s version, in a command-line console, run:
```sh
```bash
java -version
```
What needs to be verified is that `java` is in-path and that the output contains something like this:
```sh
```bash
java version "11.x.x"
...
```
or, if you have [openjdk](https://techoral.com/blog/openjdk-developers-guide.html) installed:
```sh
```bash
openjdk version "11.0.2" 2019-01-1
...
```
@@ -56,7 +56,7 @@ If otherwise the version is simply wrong, try these course of actions:
## Android SDK
If you have Android Studio installed - as most of us do, then the SDK should be available for you somewhere on your machine<sup>\*</sup>. However, for CI agents -- possibly running with no GUI, or if you simply don’t want the somewhat bloated piece of software on your computer, it is possible to simply download the SDK and tool-set, purely. Both cases are covered in Google’s [Android guide about Android Studio](https://developer.android.com/studio/). For the pure-tools option, refer to the `Command line tools only` section at the bottom.
If you have Android Studio installed - as most of us do, then the SDK should be available for you somewhere on your machine<sup>\*</sup>. However, for CI agents – possibly running with no GUI, or if you simply don’t want the somewhat bloated piece of software on your computer, it is possible to simply download the SDK and tool-set, purely. Both cases are covered in Google’s [Android guide about Android Studio](https://developer.android.com/studio/). For the pure-tools option, refer to the `Command line tools only` section at the bottom.
For more help on setting the SDK up, [this guide might be helpful](https://www.androidcentral.com/installing-android-sdk-windows-mac-and-linux-tutorial).
@@ -77,7 +77,7 @@ Fortunately, the Android team at Google offers a pretty decent alternative: **AO
_Here’s a visual comparison between the two - an SDK 28 (Android 9) AOSP emulator (left) vs. an emulator with Google APIs installed (right):_
<img src="img/android/aosp-vs-googleapi.png" alt="AOSP vs Google-API" />
![AOSP vs Google-API](img/android/aosp-vs-googleapi.png)
### Here’s how to install them using the command line
@@ -88,13 +88,13 @@ While it’s possible to do this using Android Studio, we’ll focus on the comm
1. Preliminary: Upgrade your `emulator` executable to the latest version.
_Note: It is OK if the emulator’s version is not aligned with the SDK or platform-tools' version you currently have installed (e.g. 30.x.x vs. SDK 29)_
```sh
```bash
$ANDROID_HOME/tools/bin/sdkmanager --install emulator
```
1. Install an emulator image without Google APIs:
```shell
```bash
$ANDROID_HOME/tools/bin/sdkmanager "system-images;android-28;default;x86_64"
$ANDROID_HOME/tools/bin/sdkmanager --licenses
```
@@ -105,7 +105,7 @@ While it’s possible to do this using Android Studio, we’ll focus on the comm
1. Create an emulator (i.e. AVD - Android Virtual Device):
```shell
```bash
$ANDROID_HOME/tools/bin/avdmanager create avd -n Pixel_API_28_AOSP -d pixel --package "system-images;android-28;default;x86_64"
```
@@ -141,23 +141,23 @@ Also, be sure to upgrade your emulator executable to the latest version: If it i
If the system allows saving a state (for example, in personal computers or a CI system that can start from prebaked images you can configure), we highly and strongly recommend setting up quick-boot snapshots for any emulator that is used for testing automation.
Quick-boot saves significant time otherwise wasted when emulators cold-boot from scratch. The concept becomes more prominent in environments capable of parallel-executing tests in multiple, concurrently running emulators (as when [Detox is run with multiple Jest workers](Guide.Jest.md)).
Quick-boot saves significant time otherwise wasted when emulators cold-boot from scratch. The concept becomes more prominent in environments capable of parallel-executing tests in multiple, concurrently running emulators (as when [Detox is run with multiple Jest workers](config/testRunner.md)).
This is something that we actually recommend applying in the emulator itself rather than using command-line, but we’ll include both options.
In any case, the general principle we’re going to instruct is as follows:
1. Enable auto-save for an installed / running emulator.
1. Launch it, and, when stable, terminate -- a snapshot is saved as a result.
1. Launch it, and, when stable, terminate – a snapshot is saved as a result.
1. Disable auto-save, so that future, test-tainted snapshots won’t be saved.
### Setting up a quick-boot snapshot from the Emulator
Start by launching a freshly baked emulator. Wait for it to go stable.
When running, go to settings (3 dots in the sidebar) > `Snapshots` > `Settings` tab. If not already set, select `Yes` in the `auto-save` option. This should prompt for a restart -- choose `Yes`. The emulator should restart **and save a snapshot.**
When running, go to settings (3 dots in the sidebar) > `Snapshots` > `Settings` tab. If not already set, select `Yes` in the `auto-save` option. This should prompt for a restart – choose `Yes`. The emulator should restart **and save a snapshot.**
<img src="img/android/snapshot-autosave.png" alt="Emulator auto-save menu" />
![Emulator auto-save menu](img/android/snapshot-autosave.png)
Do this again after the emulator is back up, but set `No` in the `auto-save` option. Allow it to restart yet again: it will immediately boot into the state saved as a snapshot earlier.
@@ -196,6 +196,57 @@ This is a bit more difficult, but is also applicable even for UI-less machines.
saveOnExit = false
```
### Test Butler Support (Optional)
If, when setting up your work environment, you’ve selected Google emulators with an AOSP image as the test target - as recommended,
**we strongly encourage** you would also integrate [Test Butler](https://github.com/linkedin/test-butler): in the very least - in order to suppress crash and ANR dialogs.
They are a soft spot in UI testing on Android, all around, as - when displayed,they make the UI entirely inaccessible (and thus cause tests to fail in bulks).
Setting Test Butler up for working with Detox is a bit different than explained in their guides. The process, as a whole, is twofold:
1. Preinstalling the test-butler-app APK onto the test device.
1. Integrating the test-butler-lib into your own test APK, and initializing it in a custom test runner (as explained).
The library part can be easily achieved as explained there (i.e. by using Gradle’s `androidTestImplementation`). Same goes for initialization. As for the APK, the suggested usage of Gradle’s `androidTestUtil` is scarce when running with Detox (i.e. non-native instrumentation tests). Here’s what to do instead.
> _For a complete and thorough coverage of the Test Butler integration with Detox, consider going over our [blogpost on CI execution](https://medium.com/wix-engineering/how-to-execute-android-ui-tests-on-ci-and-stay-alive-eb9089d88c1f) on medium_.
#### Solution 1: Prebaked Images
If you have control over the emulators' snapshots, simply download (see test-butler’s guide) and install the test-butler APK once (e.g. use `adb install -r -t path/to/test-butler-app.apk`), and save an updated version of the snapshot. This is the best solution.
> Note: you will have to reiterate this if you upgrade to a newer version of Test-Butler, in the future.
#### Solution 2: Dynamic Installation
Assuming you have the APK available in the system, you can dynamically have Detox automatically install it in all of the running target-emulators by utilizing `utilBinaryPaths` in your Detox configuration. Example:
```json
{
"devices": {
"emulator.oss": {
"type": "android.emulator",
"device": "...",
"utilBinaryPaths": ["relative/path/to/test-butler-app-2.2.1.apk"],
}
}
}
```
> Refer to our [configuration guide](config/apps.md) for further details on `utilBinaryPaths`.
As per _making_ the APK available - for that, we have no really good solution, for the time being (but it’s in the works). A few options might be:
a. In a custom script, have it predownloaded from Maven directly, as suggested in the Test Butler guide. For example (on a Mac / Linux):
```bash
curl -f -o ./temp/test-butler-app.apk https://repo1.maven.org/maven2/com/linkedin/testbutler/test-butler-app/2.2.1/test-butler-app-2.2.1.apk
```
> Should you decide to go this path, we recommend you add `./temp/test-butler-app.apk` to the relevant `.gitignore`.
b. (Discouraged) Add it to your source control (e.g. git), as part of the repository.
### Disclaimer
After upgrading the emulator’s binary to a newer version, it usually considers all existing snapshots invalid.
@@ -216,7 +267,7 @@ to name a few.
On Mac machines, the AVD directory typically maps to:
```sh
```bash
$HOME/.android/avd/<AVD Name>.avd/
```
@@ -231,13 +282,13 @@ The path should be similar on Linux machines, even though `$HOME` isn’t `/User
#### Shortcut for booting a verbose, visible emulator in a GUI supporting system
```shell
```bash
$ANDROID_HOME/emulator/emulator -verbose @Pixel_API_28_AOSP &
```
**Shortcut for booting a verbose, _headless_ emulator in a UI-less Linux system**
```shell
```bash
$ANDROID_HOME/emulator/emulator -verbose -no-window -no-audio -gpu swiftshader_indirect @Pixel_API_28_AOSP &
```
+62 -49
View File
@@ -13,29 +13,7 @@ We don’t have any special guidelines - just some setup walk-through!
### Environment
#### Install Homebrew
If you haven’t yet - install [`brew`](https://brew.sh/).
#### Install Node.js v12.x or newer
There’s more than one way to install Node.js:
- Download from the [official download page](https://nodejs.org/en/download/)
- Use [Homebrew](https://formulae.brew.sh/formula/node)
- Use `nvm` - if you need to allow for several versions to be installed on a single machine
The best way is to use `nvm`, but the simplest way is to use Homebrew:
```sh
brew install node
```
#### Install `npm`
Either install `npm` or check that you have it installed, using their [official guide](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm).
> **NOTE: For Detox, please use the latest `npm` version `6.x.x` (i.e not version 7.0.0 or newer).**
First, complete our [Getting Started](introduction/getting-started.mdx) guide.
#### Install the monorepo management tool, `lerna`
@@ -55,29 +33,23 @@ npm install react-native-cli --global
Watchman:
```sh
```bash
brew install watchman
```
#### iOS
For iOS, you must install Xcode and related tools. Refer to our [Setting Up an iOS Environment](Introduction.iOSDevEnv.md) guide.
#### xcpretty
You must also have `xcpretty` installed:
```sh
```bash
gem install xcpretty
```
#### Android
For Android, you need to have Java and the Android SDK properly set up. Refer to our [Setting Up an Android Development & Testing Environment](Introduction.AndroidDevEnv.md) guide.
### Detox
#### Clone Detox and Submodules
```sh
```bash
git clone [email protected]:wix/detox.git
cd detox
git submodule update --init --recursive
@@ -87,7 +59,7 @@ git submodule update --init --recursive
#### Installing and Linking Internal Projects
```sh
```bash
lerna bootstrap
```
@@ -101,17 +73,9 @@ lerna bootstrap
The following steps can be run manually in order to build / test the various components of Detox.
###### 0. (React Native ≤ 0.55.x) Fixing Compilation Issues in RN Sources
Detox Android test project uses React Native sources instead of the precompiled AAR. The test project uses React Native 0.51 and 0.53, both have issues with compilation ([fixed in 0.55](https://github.com/facebook/react-native/commit/d8bb990abc226e778e2f32c2de3c6661c0aa64e5#diff-f44163238d434a443b56bd27b3ba0578)). In order to fix this issue, from inside `detox/test` run:
```sh
mv node_modules/react-native/ReactAndroid/release.gradle node_modules/react-native/ReactAndroid/release.gradle.bak
```
###### 1. Unit Tests and Lint
```sh
```bash
lerna run test
```
@@ -131,7 +95,7 @@ npm run unit:watch
After running the tests, _Jest_ will create a coverage report you can examine:
```sh
```bash
cd detox
open coverage/lcov-report/index.html
```
@@ -166,7 +130,7 @@ FYI Android test project includes two flavors:
Each build can be triggered separately by running its Gradle assembling task (under `detox/test/android/`):
```sh
```bash
./gradlew assembleFromSourceDebug
-or-
./gradlew assembleFromBinDebug
@@ -175,7 +139,7 @@ Each build can be triggered separately by running its Gradle assembling task (un
To run from Android Studio, React Native’s `react.gradle` script may require `node` to be in path.
On MacOS, environment variables can be exported to desktop applications by adding the following to your `.bashrc`/`.zshrc`:
```sh
```bash
launchctl setenv PATH $PATH
```
@@ -183,7 +147,7 @@ launchctl setenv PATH $PATH
Under `detox/android`:
```sh
```bash
./gradlew testFullRelease
```
@@ -205,7 +169,7 @@ The [documentation website](https://wix.github.io/Detox) is built using [Docusau
To run the website locally, run the following commands:
```sh
```bash
cd website
npm install
npm start
@@ -226,4 +190,53 @@ In case you want to update the docs for a specific version, you can change the r
To update a specific version with the latest changes:
1. Remove the version from `versions.json`.
2. Run `npm run docusaurus docs:version <version>`.
1. Run `npm run docusaurus docs:version <version>`.
### TODO: Setting Detox up as a compiling dependency
This is an **alternative** to the setup process described under the previous section, on adding Detox as a dependency.
In your project’s `settings.gradle` add:
```groovy
include ':detox'
project(':detox').projectDir = new File(rootProject.projectDir, '../node_modules/detox/android/detox')
```
In your _root_ `buildscript` (i.e. `android/build.gradle`), register `google()` as a repository lookup point in all projects:
```groovy
// Note: add the 'allproject' section if it doesn’t exist
allprojects {
repositories {
// ...
google()
}
}
```
In your app’s `buildscript` (i.e. `android/app/build.gradle`) add this in `dependencies` section:
```groovy
dependencies {
// ...
androidTestImplementation(project(path: ":detox"))
}
```
In your app’s `buildscript` (i.e. `android/app/build.gradle`) add this to the `defaultConfig` subsection:
```groovy
android {
// ...
defaultConfig {
// ...
testBuildType System.getProperty('testBuildType', 'debug') // This will later be used to control the test apk build type
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
missingDimensionStrategy 'detox', 'full'
}
}
```
Please be aware that the `minSdkVersion` needs to be at least 18.
-179
View File
@@ -1,179 +0,0 @@
---
id: debugging-in-android-studio
slug: guide/debugging-in-android-studio
title: Debugging in Android Studio During Detox Tests
sidebar_label: Debugging in Android Studio
---
## Debugging in Android Studio During Detox Tests
> This flow is not standard and serves mostly for investigating weird crashes or
> when contributing to Detox itself.\
> **Don’t use it unless you have a good reason.**
### Setting Detox up as a compiling dependency
Before you go anywhere further, follow the
[Setting Detox up as a compiling dependency](Introduction.Android.md#setting-detox-up-as-a-compiling-dependency)
section from the **Detox for Android** document.
### Add a "manual" configuration to your `.detoxrc`
Locate your `.detoxrc` config file or the corresponding `detox` section in your `package.json`
and add a configuration similar to this one:
```json
{
"devices": {
"emulator": {
"type": "android.emulator",
"device": {
"avdName": "<e.g., Pixel_API_28>"
}
}
},
"apps": {
"android.debug": {
"type": "android.apk",
"binaryPath": "<path to your app binary built before>"
}
},
"configurations": {
"android.manual": {
"device": "emulator",
"app": "android.debug",
"behavior": {
"launchApp": "manual"
}
}
}
}
```
While the `behavior` section is a **mandatory** thing to include, there are a few more optional
parameters to disable various side effects and make life easier when debugging:
```diff
"behavior": {
"launchApp": "manual"
},
+ "session": {
+ "autoStart": true,
+ "debugSynchronization": 0,
+ "server": "ws://localhost:8099",
+ "sessionId": "test"
+ },
+ "artifacts": false
```
- Using a preconfigured `session` with an autostarting server removes the legwork of copying and
pasting values to the instrumentation runner launch arguments dialog every time before any launch
from the IDE. Otherwise, by default when the `session` object omitted, `server` and `sessionId`
are randomly generated for every new test session.
- The `debugSynchronization: 0` override matters only if you have a global `session` config
with `debugSynchronization` set to a positive integer value. Otherwise, it is not needed. The point
is to disable regular app polling requests during debugging, since that only can hinder the debugging.
- Setting `artifacts: false` override also matters only if you have a global `artifacts` config.
The motivation is to disable irrelevant taxing activities on the device such as capturing logs
screenshots, videos and so on.
- If your investigation addresses a specific artifact plugin glitch on the native side, then just
disable all the other plugins. See [Detox Configuration](APIRef.Configuration.md) document
for the reference.
### Run a specific test
Usually, you would want to focus on a specific test suite to save time, e.g.:
```sh
detox test -c android.manual e2e/someSuite.test.js
```
If you are using Jest as a test runner, you might want to increase the test timeout via appending
`--testTimeout 999999` to the command. For Mocha, that would be `--timeout 999999`.
> Also, if there is something you want to do step by step in JS code while debugging native, append
> `--inspect-brk` flag:
>
> ```sh
> detox test -c ios.manual e2e/someSuite.test.js --inspect-brk
> ```
>
> To learn more about debugging with `--inspect-brk`, refer to
> [Debugging — Getting Started](https://nodejs.org/en/docs/guides/debugging-getting-started/)
> on the official Node.js website.
Afterwards, you should see your test suite starting as usual until it reaches the app launch, where
Detox stops instead and prompts you to launch the app from the IDE:
```plain text
detox[53038] INFO: [AndroidDriver.js] Waiting for you to manually launch your app in Android Studio.
Instrumentation class: com.wix.detox.test.test/com.example.DetoxTestAppJUnitRunner
Instrumentation arguments:
------------------------------------
Key | Value
------------------------------------
detoxServer | ws://localhost:8099
detoxSessionId | test
------------------------------------
Press any key to continue...
```
Now it is time to switch back to Android Studio. However, if for some reason you wish to terminate the process, use `Ctrl+C` to exit.
### Launching the app
Before you launch the app from Android Studio, make sure to put breakpoints at the points of interest.
You’ll need to run your instrumentation runner with the said arguments, this is why you
should create a debug configuration of `Android Instrumented Tests` type similar to the
one below:
![Android Debug Configuration - Android Instrumented Tests](img/android-studio-debug-configuration.png)
The moment you see the app has started on the device, go back to the Terminal where Detox is
running and press any key.
As a result, you are expected to see a confirmation from Detox, e.g.:
```plain text
Found the app (com.wix.detox-example) with process ID = 16854. Proceeding...
```
Now the entire test will run as usual until it sends an action to the app, which gets trapped
in your breakpoint.
![Breakpoint is active](img/android-happy-debugging.png)
Happy debugging!
### Extra tweaks
If you feel like you see too often this timeout error while debugging:
```plain text
Waited for the new RN-context for too long! (60 seconds)
If you think that’s not long enough, consider applying a custom Detox runtime-config in DetoxTest.runTests().
```
you can temporarily hack the timeout here:
```diff
diff --git a/detox/android/detox/src/main/java/com/wix/detox/config/DetoxConfig.kt b/detox/android/detox/src/main/java/com/wix/detox/config/DetoxConfig.kt
index b33b2086..aaf8e9e2 100644
--- a/detox/android/detox/src/main/java/com/wix/detox/config/DetoxConfig.kt
+++ b/detox/android/detox/src/main/java/com/wix/detox/config/DetoxConfig.kt
@@ -1,8 +1,10 @@
package com.wix.detox.config
class DetoxConfig {
@JvmField var idlePolicyConfig: DetoxIdlePolicyConfig = DetoxIdlePolicyConfig()
- @JvmField var rnContextLoadTimeoutSec = 60
+ @JvmField var rnContextLoadTimeoutSec = Int.MAX_VALUE
fun apply() {
idlePolicyConfig.apply()
```
-150
View File
@@ -1,150 +0,0 @@
---
id: debugging-in-xcode
slug: guide/debugging-in-xcode
title: Debugging in Xcode During Detox Tests
sidebar_label: Debugging in Xcode During Detox Tests
---
## Debugging in Xcode During Detox Tests
> This is mostly useful for investigating weird crashes or when contributing to Detox itself. **This workflow isn’t standard. Don’t use it unless you have a good reason.**
### Add Detox Framework to Your Project
- Go to `node_modules/detox` and extract `Detox-ios-src.tbz`
![extracted detox-ios-src directory](img/xcode/extracted-ios-src.png)
- Drag `Detox-ios-src/Detox.xcodeproj` into your Xcode project
![Detox inside Xcode project](img/xcode/drag-src-to-project.png)
- Go to your project settings → **General** and add **Detox.framework** to **Frameworks, Libraries, and Embedded Content** (make sure **Embed & Sign** is selected under **Embed**)
![embed Detox](img/xcode/embed-detox-project.png)
> NOTE: Apps should not be submitted to the App Store with the Detox framework linked. Follow this guide only to debug Detox issues in your project. Once finished, make sure to remove **Detox.framework** from your project.
### Add a "manual" configuration to your `.detoxrc`
Locate your `.detoxrc` config file or the corresponding `detox` section in your `package.json`
and add a configuration similar to this one:
```json
{
"devices": {
"simulator": {
"type": "ios.simulator",
"device": {
"type": "<e.g., iPhone 12 Pro>"
}
}
},
"apps": {
"ios.debug": {
"type": "ios.app",
"binaryPath": "<path to your app binary built before>"
}
},
"configurations": {
"ios.manual": {
"device": "simulator",
"app": "ios.debug",
"behavior": {
"launchApp": "manual"
}
}
}
}
```
While the `behavior` section is a **mandatory** thing to include, there are a few more optional
parameters to disable various side effects and make life easier when debugging:
```diff
"behavior": {
"launchApp": "manual"
},
+ "session": {
+ "autoStart": true,
+ "debugSynchronization": 0,
+ "server": "ws://localhost:8099",
+ "sessionId": "test"
+ },
+ "artifacts": false
```
- Using a preconfigured `session` with an autostarting server removes the legwork of copying and
pasting values to the instrumentation runner launch arguments dialog every time before any launch
from the IDE. Otherwise, by default when the `session` object omitted, `server` and `sessionId`
are randomly generated for every new test session.
- The `debugSynchronization: 0` override matters only if you have a global `session` config
with `debugSynchronization` set to a positive integer value. Otherwise, it is not needed. The point
is to disable regular app polling requests during debugging, since that only can hinder the debugging.
- Setting `artifacts: false` override also matters only if you have a global `artifacts` config.
The motivation is to disable irrelevant taxing activities on the device such as capturing logs
screenshots, videos and so on.
- If your investigation addresses a specific artifact plugin glitch on the native side, then just
disable all the other plugins. See [Detox Configuration](APIRef.Configuration.md) document
for the reference.
### Run a specific test
Usually, you would want to focus on a specific test suite to save time, e.g.:
```sh
detox test -c ios.manual e2e/someSuite.test.js --testTimeout 999999
```
Forwarding an increased `testTimeout` to Jest (as shown below) is recommended to avoid false timeout errors
which are likely to be thrown if you spend too much time in debugging.
> Also, if there is something you want to do step by step in JS code while debugging native, append
> `--inspect-brk` flag:
>
> ```sh
> detox test -c ios.manual e2e/someSuite.test.js --inspect-brk
> ```
>
> To learn more about debugging with `--inspect-brk`, refer to
> [Debugging — Getting Started](https://nodejs.org/en/docs/guides/debugging-getting-started/)
> on the official Node.js website.
Afterwards, you should see your test suite starting as usual until it reaches the app launch, where
Detox stops instead and prompts you to launch the app from the IDE:
```plain text
detox[16804] INFO: [SimulatorDriver.js] Waiting for you to manually launch your app in Xcode.
Make sure to pass the launch arguments listed below:
-detoxServer ws://localhost:8099
-detoxSessionId com.wix.detox-example
Press any key to continue...
```
You’ll need to run your app with the said arguments from Xcode:
![Xcode - Edit Schema - Arguments tab](img/xcode/edit-schema-arguments.png)
### Launching the app
Before you launch the app, make sure to [put breakpoints](https://developer.apple.com/documentation/xcode/setting-breakpoints-to-pause-your-running-app) at the points of interest, e.g.:
![put a breakpoint in the native code](img/xcode/putting-a-breakpoint.png)
Launch the app with the debugger attached:
![launching the app](img/xcode/launch-app-with-debugger.png)
The moment you see the app is idle, go back to the Terminal where Detox is running
and press any key. If you wish to terminate the process for some reason, use Ctrl+C.
In a couple of seconds you are expected to see a confirmation from Detox, e.g.:
```plain text
Found the app (com.wix.detox-example) with process ID = 16854. Proceeding...
```
Now the entire test will run as usual until it sends an action to the app, which gets trapped
in your breakpoint. Now, when you are there, we wish you happy debugging!
+25 -29
View File
@@ -13,57 +13,53 @@ The main idea behind this workflow is to run your app in debug with Detox on a s
### Step 1: Build Your App in Debug
Detox is going to need the executable for your app. This means we need to build it first. Since we want a build that’s connected to the live React Native packager (to update bundle changes), we’re going to need a _debug_ build.
Detox is going to need the executable for your app. This means we need to build it first.
Since we want a build that’s connected to the live React Native packager (to update bundle changes),
we’re going to need a _debug_ build:
There are multiple ways to build your app, let’s find the alternative you like best:
```bash
detox build -c ios.sim.debug # or android.emu.debug
```
- **I like to build my app by clicking "Play" in Xcode** — This isn’t a great approach here because using Xcode IDE to build your app will place the executable in an internal directory which path that is difficult to predict (`~/Library/Developer/Xcode/DerivedData/...`). This means we won’t be able to tell Detox where to find it. Although you can change the default `derivedData` path by altering your Xcode settings, we encourage you to try the alternative ways to build.
If you’d like to debug Detox with Xcode, see [Debugging In Xcode](Guide.DebuggingInXcode.md).
- **I like to build my app with `react-native run-ios`** — The official React Native command line tools provide a script to build your app from terminal. Go to your project root and type `react-native run-ios`. This will build the app in debug and place the executable in the folder `ios/build/Build/Products/Debug-iphonesimulator`. This is a great way to build because it’s easy to specify this path in Detox configuration inside `package.json`. This is actually the path we specified in the getting started tutorial.
```sh
react-native run-ios
```
- **I like to build my app with `detox build`** — During the installation instructions, we provided Detox configuration in `package.json` with a command line to build your app executable. We can execute this build command by going to the project root and typing `detox build`. Please make sure that you’re using a Detox configuration that builds a debug version of your app. The default we specified in the getting started tutorial should work.
```sh
detox build
```
> TIP: Running `react-native run-ios` will also start a simulator and install your app on it, running `detox test` later will possibly start a different simulator, so you’ll find yourself with two open simulators. You can safely close the simulator started by `react-native`, everything will continue working as expected.
Check out [Introduction > Building with Detox](introduction/building-with-detox.mdx) for more details.
### Step 2: Make Sure Your React-Native Packager is Running
If you can’t see a React Native packager instance running in a terminal, you can run it manually by typing:
```sh
react-native start
```bash
npx react-native start
```
The packager instance will reload the JavaScript bundle of your app when you press CMD+R in the simulator window. This will allow you to make modifications in your app codebase.
The packager instance will reload the JavaScript bundle of your app when you press CMD+R in the simulator window.
This will allow you to make modifications in your app codebase.
### Step 3: Run Detox Tests
Type the following inside your project root:
```sh
detox test
```bash
detox test -c ios.sim.debug # or android.emu.debug
```
This will use Detox to find the app executable we’ve built in step 1, install it on a simulator and run Detox tests against it.
This will use Detox to find the app executable we’ve built in step 1, install it on the device and run Detox tests against it.
### Step 4: Make Changes to Your App’s Codebase as Usual
You can keep working on the JavaScript codebase of your app as usual. As long as you keep the simulator from step 3 running, you’ll be able to press CMD+R inside and reload your app with the new changes.
You can keep working on the JavaScript codebase of your app as usual.
As long as you keep the simulator from step 3 running, you’ll be able to press CMD+R inside and reload your app with the new changes.
### Step 5: Re-run Detox Tests Without Re-installing the App
You can make changes to your Detox tests as well. When you want to run your tests on the simulator, we recommend using the following command:
You can make changes to your Detox tests as well. When you want to re-run your tests on the device,
we recommend adding `--reuse` flag to save your time when running the tests.
```sh
detox test --reuse
```bash
detox test -c ios.sim.debug --reuse # or android.emu.debug
```
The reuse option will prevent Detox from compiling and re-installing your app again in the simulator. The tests will simply run against the current app instance currently running in the simulator. This will make the process much faster.
By default, Detox reinstalls the app before picking every next test suite which is redundant in this situation
since your app code changes are delivered via network with React Native packager, and the app binary itself does
not change.
You should not use this option if you made native code changes or if your app relies on local ("disk") storage.
-14
View File
@@ -1,14 +0,0 @@
---
id: expo
slug: guide/expo
title: Expo
sidebar_label: Expo
---
## Expo
**Note**: Expo support with Detox is entirely a community driven effort. We have no specific support in Detox for Expo applications (ejected or otherwise).
If you are seeing an issue, it is most likely not an issue with Detox itself, but with the Expo runtime or with an incorrect Detox setup. For support on how to use Detox with Expo, you should contact the Expo team or the Expo community.
General Expo issues will no longer be allowed in the Detox issue tracker. If you’ve investigated the Expo runtime or your app, and found a genuine issue with Detox, please open an issue.
-194
View File
@@ -1,194 +0,0 @@
---
id: jest
slug: guide/jest
title: Jest Setup Guide
sidebar_label: Jest Setup Guide
---
## Jest Setup Guide
> **NOTE: This article previously focused on deprecated `jest-jasmine2` runner setup, and if you nevertheless need to access it, [follow this Git history link](https://github.com/wix/Detox/blob/ef466822129a4befcda71111d02b1a334539889b/docs/Guide.Jest.md).**
This guide describes how to install [Jest](https://jestjs.io) as a test runner to be used by Detox for running the E2E tests.
### Introduction
As already mentioned in the [Getting Started](Introduction.GettingStarted.md#set-up-a-test-runner) guide, Detox itself does not effectively run tests logic, but rather delegates that responsibility onto a test runner. At the moment, Jest is the only recommended choice, for many reasons, including - but not limited to, parallel test suite execution capability, and complete integration with Detox API.
By the way, Jest itself — much like Detox, also does not effectively run any tests. Instead, it is more of a dispatcher and orchestrator of multiple instances of a delegated runner capable of running in parallel. For more info, refer to [this video](https://youtu.be/3YDiloj8_d0?t=2127) (source: [Jest architecture](https://jestjs.io/docs/en/architecture)).
### Installation
**Disclaimer:**
1. Here we focus on installing Detox on _new projects_. If you’re migrating a project with an existing Detox installation, please apply some common sense while using this guide.
1. These instructions are relevant for `jest@^27.2.5` and `[email protected]`. They should likely work for the newer `jest` versions too, but for **the older ones** (26.x, 25.x) — **they will not, due to blocking issues.**
#### 1. Install Jest
Before starting with Jest setup, be sure to complete the preliminary sections of the [Getting Started](Introduction.GettingStarted.md) guide.
Afterward, install the respective npm package:
```bash npm2yarn
npm install -D "jest@>=27.2.5"
```
**NOTE:** The command will install the _latest Jest version_. However, `@>=27.2.5` addendum is recommended just to be on the safe side in a common scenario, when a `package-lock.json`
generated by an official React Native project template limits Jest version to a very old `26.x`, maybe due to some optimization mechanism.
#### 2. Set up Test-code Scaffolds
Run the automated init script:
```sh
detox init -r jest
```
> **Note:** errors occurring in the process may appear in red.
If things go well, the following will be created:
- An `e2e/` folder in your project root
- An `e2e/config.json` file; [example](https://github.com/wix/Detox/tree/master/examples/demo-react-native-jest/e2e/config.json)
- An `e2e/environment.js` file; [example](https://github.com/wix/Detox/tree/master/examples/demo-react-native-jest/e2e/environment.js)
- An `e2e/starter.test.js` file with content similar to [this](https://github.com/wix/Detox/tree/master/examples/demo-react-native-jest/e2e/app-hello.e2e.ts).
#### 3. Fix / Verify
Even if `detox init` passes well, and everything is green, we still recommend going over the checklist below. You can also use our example project, [`demo-react-native-jest`](https://github.com/wix/Detox/tree/master/examples/demo-react-native-jest), as a reference in case of ambiguities.
##### .detoxrc.json
| Property | Value | Description |
| -------------- | ----------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| `testRunner` | `"jest"` | _Required._ Should be `"jest"` for the proper `detox test` CLI functioning. |
| `runnerConfig` | (optional path to Jest config file) | _Optional._ This field tells `detox test` CLI where to look for Jest’s config file. If omitted, the default value is `e2e/config.json`. |
A typical Detox configuration in `.detoxrc.json` file looks like:
```json
{
"runnerConfig": "e2e/config.json",
"devices": {
"simulator": {
"type": "ios.simulator",
"device": {
"type": "iPhone 12 Pro Max"
}
}
},
"apps": {
"ios.release": {
"type": "ios.app",
"binaryPath": "ios/build/Build/Products/Release-iphonesimulator/example.app",
"build": "<...xcodebuild command...>",
}
},
"configurations": {
"ios.sim.release": {
"device": "simulator",
"app": "ios.release"
}
}
}
```
##### `e2e/config.json`
| Property | Value | Description |
| ----------------- |-----------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `maxWorkers` | `1` | _Recommended._ It prevents potential overallocation of mobile devices according to the default logic of Jest (`maxWorkers = cpusCount — 1`) for the default workers count. To override it, [use CLI arguments](APIRef.DetoxCLI.md#test), or see [Jest documentation](https://jestjs.io/docs/configuration#maxworkers-number--string) if you plan to change the default value in the config. |
| `testEnvironment` | `"./environment"` | _Required._ Needed for the proper functioning of Jest and Detox. See [Jest documentation](https://jestjs.io/docs/en/configuration#testenvironment-string) for more details. |
| `testRunner` | `"jest-circus/runner"` | _Required._ Needed for the proper functioning of Jest and Detox. See [Jest documentation](https://jestjs.io/docs/en/configuration#testrunner-string) for more details. |
| `testTimeout` | `120000` | _Required_. Overrides the default timeout (5 seconds), which is usually too short to complete a single end-to-end test. |
| `reporters` | `["detox/runners/jest/reporter"]` | _Recommended._ Sets up our streamline replacement for [Jest’s default reporter](https://jestjs.io/docs/en/configuration#reporters-array-modulename-modulename-options), which removes Jest’s default buffering of `console.log()` output. That is helpful for end-to-end tests since log messages appear on the screen without any artificial delays. |
| `verbose` | `true` | _Conditional._ Must be `true` if above you have replaced Jest’s default reporter with Detox’s `reporter`. Optional otherwise. |
A typical `jest-circus` configuration in `e2e/config.json` file would look like:
```json
{
"testRunner": "jest-circus/runner",
"testEnvironment": "./environment",
"testTimeout": 120000,
"reporters": ["detox/runners/jest/reporter"],
"verbose": true
}
```
##### `e2e/environment.js`
If you are not familiar with Environment concept in Jest, you could check [their documentation](https://jestjs.io/docs/en/configuration#testenvironment-string).
For Detox, having a `CustomDetoxEnvironment` class derived from `NodeEnvironment` enables implementing cross-cutting concerns such as taking screenshots the exact moment a test function (it/test) or a hook (e.g., beforeEach) fails, skip adding tests if they have `:ios:` or `:android:` within their title, starting device log recordings before test starts and so on.
API of `CustomDetoxEnvironment` is not entirely public in a sense that there’s no guide on how to write custom `DetoxCircusListeners` and override `initDetox()` and `cleanupDetox()` protected methods, since this is not likely to be needed for typical projects, but this is under consideration if there appears specific demand. You may want to check out this [simple example](https://github.com/wix/Detox/pull/2009#issuecomment-648971528) of overriding `initDetox()`, or some [alternative approaches](https://github.com/wix/Detox/pull/2009#issuecomment-649342823) to overriding `initDetox()`.
```js
const {
DetoxCircusEnvironment,
SpecReporter,
WorkerAssignReporter,
} = require('detox/runners/jest');
class CustomDetoxEnvironment extends DetoxCircusEnvironment {
constructor(config, context) {
super(config, context);
// Can be safely removed, if you are content with the default value (=300000ms)
this.initTimeout = 300000;
// This takes care of generating status logs on a per-spec basis. By default, Jest only reports at file-level.
// This is strictly optional.
this.registerListeners({
SpecReporter,
WorkerAssignReporter,
});
}
}
module.exports = CustomDetoxEnvironment;
```
**Notes:**
- The custom `SpecReporter` is recommended to be registered as a listener. It takes care of logging on a per-spec basis (i.e. when `it('...')` functions start and end) — which Jest does not do by default.
- The custom `WorkerAssignReporter` prints for every next test suite which device is assigned to its execution.
This is how a typical Jest log output looks when `SpecReporter` and `WorkerAssignReporter` are enabled in `streamline-reporter` is set up in `config.json` and
`SpecReporter` added in `e2e/environment.js`:
![Streamlined output](img/jest-guide/streamlined_logging.png)
### Writing Tests
There are some things you should notice:
- Don’t worry about mocks being used, Detox works on the compiled version of your app.
- Detox exposes its primitives (`expect`, `device`, ...) globally, it will override Jest’s global `expect` object.
### Parallel Test Execution
Through Detox' CLI, Jest can be started with [multiple workers](Guide.ParallelTestExecution.md) that run tests simultaneously, e.g.:
```bash
detox test --configuration <yourConfigurationName> --workers 2
```
In this mode, Jest effectively assigns one worker per each test file.
Per-spec logging offered by the `SpecReporter` mentioned earlier, does not necessarily make sense, as the workers' outputs get mixed up.
By default, we disable `SpecReporter` in a multi-workers environment.
If you wish to force-enable it nonetheless, the [`--jest-report-specs`](APIRef.DetoxCLI.md#test) CLI option can be used with `detox test`, e.g.:
```bash
detox test --configuration <yourConfigurationName> --workers 2 --jest-report-specs
```
### How to Run Unit and E2E Tests in the Same Project
- Create different Jest configs for unit and E2E tests, e.g. in `e2e/config.json` (for Detox) and `jest.config.js`
(for unit tests). For example, in Jest’s E2E config you can set `testMatch` to look for `<rootDir>/e2e/**/*.test.js$`
glob, and this way avoid accidental triggering of unit tests in your `src/` or `lib/` folder.
- To run your E2E tests, use `detox test` command (or `npx detox test`, if you haven’t installed `detox-cli`).
@@ -1,13 +1,13 @@
---
id: launch-args
slug: api/launch-args
title: Launch Arguments
sidebar_label: Launch Arguments
title: Using Launch Arguments
sidebar_label: Using Launch Arguments
---
## Launch Arguments
In Detox, the app under test is launched via an explicit call to [`device.launchApp()`](APIRef.DeviceObjectAPI.md). Through various means, Detox enables specifying a set of user-defined arguments (key-value pairs) to be passed on to the app when launched, so as to make them available inside the launched app itself at runtime (both on the native side, and - if applicable, on the JavaScript side).
In Detox, the app under test is launched via an explicit call to [`device.launchApp()`](api/device.md). Through various means, Detox enables specifying a set of user-defined arguments (key-value pairs) to be passed on to the app when launched, so as to make them available inside the launched app itself at runtime (both on the native side, and - if applicable, on the JavaScript side).
### Motivation
@@ -28,12 +28,12 @@ In this context, launch argument are useful for implementing step [#3](https://g
User-defined launch arguments specification is very flexible, and can be defined on 4 levels:
| Level | Description |
| ----------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 1. Static Configuration | As a part of a static [Detox configuration](APIRef.Configuration.md), using the `launchArgs` property.<br />This is can sufficient, for example, if you only require one mock server instance, and can use the same static port throughout the entire testing execution session. |
| 2. Static via CLI | As arguments specified explicitly in the [command-line](APIRef.DetoxCLI.md) execution of `detox test`, using `--app-launch-args`. |
| 3.`device.appLaunchArgs` | Dynamically, using the [`device.appLaunchArgs`](APIRef.DeviceObjectAPI.md#deviceapplaunchargs) API, which initially holds the static configuration, and then allows for the modification of it before applied through `device.launchApp()`.<br/>Mostly required in complex test environments, where the servers and ports are dynamic, and are determined via distinct software components (e.g. separate test kits). |
| 4. `device.launchApp()` with `launchArgs` | Dynamically and explicitly, using on-site arguments specified in calls to [`device.launchApp()`](APIRef.DeviceObjectAPI.md#devicelaunchappparams) through the `launchArgs` parameter.<br />Ideal for fairly simple test environments, where the ports are dynamic but are in complete control of the user. |
| Level | Description |
| ----------------------------------------- |-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 1. Static Configuration | As a part of a static [Detox configuration](config/overview.md), using the `launchArgs` property.<br />This is can sufficient, for example, if you only require one mock server instance, and can use the same static port throughout the entire testing execution session. |
| 2. Static via CLI | As arguments specified explicitly in the [command-line](api/detox-cli.md) execution of `detox test`, using `--app-launch-args`. |
| 3.`device.appLaunchArgs` | Dynamically, using the [`device.appLaunchArgs`](api/device.md#deviceapplaunchargs) API, which initially holds the static configuration, and then allows for the modification of it before applied through `device.launchApp()`.<br/>Mostly required in complex test environments, where the servers and ports are dynamic, and are determined via distinct software components (e.g. separate test kits). |
| 4. `device.launchApp()` with `launchArgs` | Dynamically and explicitly, using on-site arguments specified in calls to [`device.launchApp()`](api/device.md#devicelaunchappparams) through the `launchArgs` parameter.<br />Ideal for fairly simple test environments, where the ports are dynamic but are in complete control of the user. |
**Important: Arguments specified in each level take precedence over equivalent underlying levels**.
+5 -8
View File
@@ -2,11 +2,8 @@
id: migration
slug: guide/migration
title: Migration Guide
sidebar_label: Migration Guide
---
## Migration Guide
We are improving Detox API as we go along, sometimes these changes require us to break the API in order for it to make more sense. These migration guides refer to breaking changes. If a newer version has no entries in this document, it means it does not require special migration steps. Refer to the release notes of the latter builds to learn about their improvements and changes.
### 19.2
@@ -34,7 +31,7 @@ You’ll need to find those places and apply trivial fixes like shown below:
**Version 19 is not really a breaking change!**
We decided to bump Detox into a major version release, nonetheless, because it is breaking for projects that sport [custom Detox drivers](Guide.ThirdPartyDrivers.md), such as [`detox-puppeteer`](https://github.com/ouihealth/detox-puppeteer).
We decided to bump Detox into a major version release, nonetheless, because it is breaking for projects that sport [custom Detox drivers](articles/third-party-drivers.md), such as [`detox-puppeteer`](https://github.com/ouihealth/detox-puppeteer).
If you are a maintainer of such a project, and you wish to upgrade your Detox dependency to 19 (kudos! :clap:), follow this step-by-step migration guide; You can refer to [this pull-request](https://github.com/ouihealth/detox-puppeteer/pull/13), which does that for the `detox-puppeteer` project.
@@ -49,7 +46,7 @@ The core of the change is that Detox' drivers framework is **no longer a single
> You can find a visual explanation, [here](https://github.com/wix/Detox/files/7338121/pre-multiapps-rfc.pdf).
In addition, the runtime driver is no longer state-less -- basically, allowing implementation to hold any state that is required in identifying and managing the associated device.
In addition, the runtime driver is no longer state-less – basically, allowing implementation to hold any state that is required in identifying and managing the associated device.
##### How to migrate
@@ -90,7 +87,7 @@ Add the new class to the `module.exports` list, under the name: `ArtifactPlugins
- Optionally rename your class from `PuppeteerDriver` to `PuppeteerRuntimeDriver`.
- In the methods remaining in the class accepting the `deviceId` arg: **remove the `deviceId` arg entirely**. This might break your implementation - don’t worry, continue reading.
- If applicable, change the signature of the class' c'tor to accept the cookie as its 2nd argument (instance previously allocated in `PuppeteerAllocationDriver.allocate()`). Save data from the cookie as part of the driver’s state, in order to unbreak your implementation, following the previous step.
- Add two methods: `getExternalId()` and `getDeviceName()`. Implement them such that they would comply with the `device.id` and `device.name` [API contracts](APIRef.DeviceObjectAPI.md), respectively.
- Add two methods: `getExternalId()` and `getDeviceName()`. Implement them such that they would comply with the `device.id` and `device.name` [API contracts](api/device.md), respectively.
Export the runtime driver class in the `module.exports` list as `RuntimeDriverClass`, **instead of `DriverClass`.**
@@ -101,7 +98,7 @@ For issue related to these migrations, approach us by [submitting an issue on Gi
### 18.6.0
Detox has normalized the configuration format, so that along with the combined `configurations` object you now can define your `devices` and `apps` separately.
Please refer to the [configuration doc](https://github.com/wix/Detox/blob/18.6.0/docs/APIRef.Configuration.md) to obtain more details.
Please refer to the [configuration doc](config/overview.md) to obtain more details.
This change is backward-compatible, although the new format is now the recommended option.
### 18.0
@@ -243,7 +240,7 @@ The following APIs have been deprecated, but is still available
- `toBeNotVisible()`—deprecated in favor of `not.toBeVisible()` (iOS, Android)
- `toNotExist()`—deprecated in favor of `not.toExist()` (iOS, Android)
Make sure to read the API reference for [matchers](https://github.com/wix/Detox/blob/master/docs/APIRef.Matchers.md), [actions](https://github.com/wix/Detox/blob/master/docs/APIRef.ActionsOnElement.md) and [expectations](https://github.com/wix/Detox/blob/master/docs/APIRef.Expect.md).
Make sure to read the API reference for [matchers](api/matchers.md), [actions](api/actions.md) and [expectations](api/expect.md).
If you see unexpected results, make sure to open an issue.
-10
View File
@@ -1,10 +0,0 @@
---
id: mocha
slug: guide/mocha
---
## Mocha Setup Guide
Mocha test runner support is removed since Detox v20.
Please migrate your E2E tests to Jest according to [this guide](Guide.Jest.md).
+18 -14
View File
@@ -5,9 +5,13 @@ title: Mocking
sidebar_label: Mocking
---
## Mocking
# Mocking
> **NOTE: This article previously focused on the older React Native versions (`<0.59`), so if you need to access it, [follow this Git history link](https://github.com/wix/Detox/blob/01ad250fe4168502a57339b8bcab0ec5a5c89e4b/docs/Guide.Mocking.md).**
:::info
This article previously focused on the older React Native versions (`<0.59`), so if you need to access it, [follow this Git history link](https://github.com/wix/Detox/blob/01ad250fe4168502a57339b8bcab0ec5a5c89e4b/docs/Guide.Mocking.md).
:::
Mocking is an integral part of testing.
You may want to use mocks to alter specific behavior of your app during tests, e.g., to:
@@ -34,7 +38,7 @@ Thanks to Metro bundler, there are two modes your React Native application can r
There are two ways to configure the _Metro bundler_ to use your mocks: quick (**debug mode** only) and universal.
Let's start with the quicker way.
### Quick flow
## Quick flow
1. Pick a module that you are going to mock, e.g.:
@@ -58,7 +62,7 @@ Let's start with the quicker way.
1. Stop your _Metro bundler_ if it has been already running, and run it again with the corresponding file extension override, e.g.:
```sh
```bash
npx react-native start --sourceExts mock.js,js,json,ts,tsx
```
@@ -67,17 +71,17 @@ Let's start with the quicker way.
> CAVEAT: whichever file extension you might take for the mock files – make sure you don’t accidentally "pick up" unforeseen file overrides from `node_modules/**/*.your-extension.js`!
> _Metro bundler_ does not limit itself to your project files only – applying those `--sourceExts` also affects the resolution of the `node_modules` content!
### Configuring Metro bundler
## Configuring Metro bundler
While the mentioned way is good enough for the **debug mode**, it falls short for the **release builds**. The problem is that the `--sourceExts` argument is supported only by `react-native start` command. Hence, you’d need a CLI-independent way to configure your Metro bundler, and that is patching your project's `metro.config.js`:
```diff
/**
* Metro configuration for React Native
* https://github.com/facebook/react-native
*
* @format
*/
```diff title="metro.config.js"
/**
* Metro configuration for React Native
* https://github.com/facebook/react-native
*
* @format
*/
+const defaultSourceExts = require('metro-config/src/defaults/defaults').sourceExts;
module.exports = {
@@ -101,13 +105,13 @@ This way, we are enforcing a custom convention that if the Metro bundler finds t
Therefore, to start the Metro bundler in the mocked mode, you would run something like:
```sh
```bash
MY_APP_MODE=mocked npx react-native start
```
This principle stays the same for the **release mode**, although the build commands might differ depending on the platform and a specific script:
```sh
```bash
export MY_APP_MODE=mocked
# from now on, even an implicit run of Metro bundler will use our override
+2 -2
View File
@@ -9,7 +9,7 @@ sidebar_label: Parallel Test Execution
Detox can leverage multi worker support of JS test runners ([Jest](http://jestjs.io/docs/en/cli#maxworkers-num), etc.).
By default `detox test` will run the test runner with one worker. Worker count can be controlled by adding `--workers n` to `detox test`, read more in [`detox-cli` section](APIRef.DetoxCLI.md#test).
By default `detox test` will run the test runner with one worker. Worker count can be controlled by adding `--maxWorkers <N>` to `detox test`, read more in [`detox-cli` section](api/detox-cli.md#test).
### Device Creation
@@ -25,7 +25,7 @@ Simulators/emulators run on a different process, outside of node, and require so
> - `detox-cli` makes sure `device.registry.state.lock` is cleaned whenever it executes.
> - If you use Detox without `detox-cli` make sure you delete or reset the lock file before running tests.
>
> ```sh
> ```bash
> echo "[]" > ~/Library/Detox/device.registry.state.lock
> ```
+76
View File
@@ -0,0 +1,76 @@
---
id: proguard-configuration
slug: guide/proguard-configuration
---
# ProGuard configuration
:::tip
You can skip this guide if you are working solely with debug builds (`android.emu.debug`, etc.),
but as soon as you move to the **release builds**, where the native code gets minified and obfuscated,
you are going to have problems with Detox if you leave your ProGuard rules unconfigured.
:::
Since Detox relies on
[Android Reflection API](https://developer.android.com/reference/java/lang/reflect/package-summary)
to integrate with React Native on Android, you should keep [ProGuard minification](https://developer.android.com/studio/build/shrink-code)
under tight control. Otherwise, you'll be seeing Detox crashing or hanging up infinitely upon an attempt to
run tests with your app built in **release mode**.
To fix that, you'd need to return to your app build script:
```diff title="app/build.gradle"
buildTypes {
…
// highlight-next-line
release {
minifyEnabled true
// highlight-next-line
proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
// highlight-next-line
+ proguardFile "${rootProject.projectDir}/../node_modules/detox/android/detox/proguard-rules-app.pro"
}
}
```
1. `release` is typically the default proguard-enabled build-type
1. Typical pro-guard definitions. Check out Android docs to get to know more.
1. Detox-specific additions to pro-guard
:warning: **Note:** In order for Detox to be able to work properly, in `proguard-rules-app.pro`,
it effectively declares rules that retain most of React-Native’s code
(i.e. keep it unminified, unobfuscated) in your **production** APK.
Though generally speaking, this should not be an issue (as React-Native is an open-source project),
there are ways around that, if it bothers you.
For example, running your E2E over a build-type specifically designed to run E2E tests using Detox would do the trick
– roughly, like so (in `app/build.gradle`):
```groovy
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.release
}
releaseE2E {
initWith release
setMatchingFallbacks('release')
proguardFile "${rootProject.projectDir}/../node_modules/detox/android/detox/proguard-rules-app.pro"
}
}
```
Here we utilize Gradle’s `initWith` to easily define `releaseE2E` in a way that is identical to the `release` build-type, with the exception of considering Detox' `proguard-rules-app.pro` in the minification process.
Following the example, you would then have to build your app using `gradlew assembleReleaseE2E` rather than `gradlew assembleRelease` before running Detox, and instruct Detox (i.e. via `binaryPath` in the Detox configuration file) to use the APK resulted specifically by _that_ Gradle target (e.g. in `app/build/apk/releaseE2E/app-releaseE2E.apk` instead of the equivalent `app/build/apk/release/app-release.apk`).
> Note: if your app contains flavors – that makes things a bit trickier, but the approach can generally be adjusted to support that as well.
**Last but not least:** If you’re having issue with Detox' ProGuard rules, please report them [here](https://github.com/wix/Detox/issues/new/choose).
A special thanks to [@GEllickson-Hover](https://github.com/GEllickson-Hover) for reporting issues related to obfuscation in [#2431](https://github.com/wix/Detox/issues/2431).
-34
View File
@@ -1,34 +0,0 @@
---
id: running-locally
slug: guide/running-locally
title: Running Locally
sidebar_label: Running Locally
---
## Running Locally
If your app is ready and does not require any active development, you can write your tests using this workflow and run them locally on your machine. This is convenient for developing your test suite without actively developing your app.
This is the basic workflow. It takes your app executable and runs Detox tests against it.
### Step 1: Build Your App
Detox is going to need the executable for your app. This means we need to build it first. We’re going to use the Detox command line tools to build the app. During the installation, we’ve specified the actual build command line inside `package.json` under the `detox` configuration section.
Build the app by typing in terminal inside your project root:
```sh
detox build
```
### Step 2: Run Detox Tests
Type the following inside your project root:
```sh
detox test
```
This will use Detox to find the app executable we’ve built in step 1, install it on a simulator and run Detox tests against it.
**Note:** If you have multiple configurations, you will need to specify the configuration to test.
+9 -11
View File
@@ -17,13 +17,13 @@ Every install of Detox also triggers a `postinstall` script in its `package.json
You can either delete the folder manually:
```sh
```bash
rm -rf ~/Library/Detox
```
or run:
```sh
```bash
detox clean-framework-cache
```
@@ -34,8 +34,6 @@ On every test run, Detox rewrites a few temporary files in `DETOX_LIBRARY_ROOT_P
1. The respective iOS and Android lockfiles to tell apart the busy and the available devices for use with multiple workers:
- `device.registry.state.lock`
- `android-device.registry.state.lock`.
1. A plain text file with the line-separated list of last failed test files to rerun via `-R <retries-count>` CLI feature:
- `last-failed.txt`.
The location of `DETOX_LIBRARY_ROOT_PATH` may vary depending on the operating system:
@@ -53,13 +51,13 @@ The location of `DETOX_LIBRARY_ROOT_PATH` may vary depending on the operating sy
To support the "multiple workers" feature on iOS, Detox clones simulator instances when there aren’t enough available ones.
The autogenerated simulators have names with `-Detox` suffix appended, so you can easily spot them with:
```sh
```bash
xcrun simctl list | grep "-Detox"
```
To delete a simulator, you can use:
```sh
```bash
xcrun simctl delete <uuid>
```
@@ -71,13 +69,13 @@ Forced exits may result in leaving some temporary files behind.
To ensure there are no temporary artifact files (logs, screenshots, etc.), you can run:
```sh
```bash
rm -rf $TMPDIR/*.detox.*
```
If you wish to clean up your iOS simulators from the installed apps and other customizations, just run the erase procedure for the relevant ones:
```sh
```bash
xcrun simctl erase <uuid>
```
@@ -85,15 +83,15 @@ xcrun simctl erase <uuid>
The advice for iOS applies to the Android virtual devices as well. To wipe user files on a specific AVD, run:
```sh
```bash
emulator -avd <your_AVD> -wipe-data
```
If you have to clean temporary Detox files from an individual booted device, look out for files like `11159175_0.log` in `/sdcard` folder.
You can try deleting them using a simple wildcard like below or use your own:
```sh
adb -s <emulator-port> shell rm -rf /sdcard/*_*.*
```bash
adb -s <emulator-port> shell rm -rf /sdcard/*_*.*
```
### Detox CLI
-395
View File
@@ -1,395 +0,0 @@
---
id: android
slug: introduction/android
title: Detox for Android
sidebar_label: Detox for Android
---
<!-- markdownlint-configure-file { "no-trailing-punctuation": 0 } -->
## Detox for Android
### Breaking Changes :warning:
**If you are installing Detox for Android for the first time, you can skip over to the setup section.**
> Follow our [Migration Guide](Guide.Migration.md) for instructions on how to upgrade from older versions.
- **In version 11 we switched to using Android Espresso of Android’s new [androidx.\* support libraries](https://developer.android.com/jetpack/androidx/).** We did this in order to stay up to date with Google’s latest features and bug fixes, in the hopes of using them to improve our own Android support (which gets better every day!).
- **In version 10, we’ve made [Kotlin](https://kotlinlang.org/) mandatory for integrating Detox into your Android project.** In the very least, you must include the Kotlin Gradle plugin in your project, as we shall see later on. Nevertheless, this is a breaking change so bear that in mind when upgrading. In any case, worry not of the impact on your app, as - unless you effectively use Kotlin in your own native code, **there will be no impact on the final APK**, in terms of size and methods count.
- **As of version 7** we require Android Gradle plugin 3.0.0 or newer. This is a breaking change that makes it impossible to support previous Android Gradle plugin versions.
<https://developer.android.com/studio/build/gradle-plugin-3-0-0-migration.html>
For older Android Gradle plugin support use `[email protected]` instead ([previous setup guide here](https://github.com/wix/detox/blob/97654071573053def90e8207be8eba011408f977/docs/Introduction.Android.md)).
**Note: As a rule of thumb, we consider all old major versions discontinued; We only support the latest Detox major version.**
### Setup :gear:
#### 1. Preliminary
Run through the basic steps of the [Getting Started guide](Introduction.GettingStarted.md), such as the environment and tools setup.
#### 2. Apply Detox Configuration
Whether you’ve selected to apply the configuration in a `.detoxrc.json` or bundle it into your project’s `package.json` (under the `detox` section), this is what the configuration should roughly look like for Android:
```json
{
"devices": {
"emulator": {
"type": "android.emulator",
"device": {
"avdName": "Pixel_API_28"
}
}
},
"apps": {
"android.debug": {
"type": "android.apk",
"binaryPath": "android/app/build/outputs/apk/debug/app-debug.apk",
"build": "cd android && ./gradlew assembleDebug assembleAndroidTest -DtestBuildType=debug && cd .."
},
"android.release": {
"type": "android.apk",
"binaryPath": "android/app/build/outputs/apk/release/app-release.apk",
"build": "cd android && ./gradlew assembleRelease assembleAndroidTest -DtestBuildType=release && cd .."
}
},
"configurations": {
"android.emu.debug": {
"device": "emulator",
"app": "android.debug"
},
"android.emu.release": {
"device": "emulator",
"app": "android.release"
}
}
}
```
> For a comprehensive explanation of Detox configuration, refer to the [dedicated API-reference guide](APIRef.Configuration.md).
Pay attention to `-DtestBuildType`, set either to `debug` or `release` according to the main APK type.
Following device types could be used to control Android devices:
- `android.emulator`. Boot stock Android-SDK emulator (AVD) with provided `name`, for example `Pixel_API_28`.
- `android.attached`. Connect to already-attached android device. The device should be listed in the output of `adb devices` command under provided `name`.
Use this type to connect to Genymotion emulator.
The `avdName` property accepts a regular expression pattern that allows to specify the pool of device candidates to which you wish to connect. Use this property to run tests in parallel on multiple attached devices.
For a complete, working example, refer to the [Detox example app](https://github.com/wix/Detox/tree/master/examples/demo-react-native/detox.config.js).
##### Using product flavors
If you are using custom [`productFlavors`](https://developer.android.com/studio/build/build-variants#product-flavors) the config needs to be applied a bit differently. This example shows how a `beta` product flavor would look for both debug and release build types:
```json
"detox" : {
"devices": {
"emulator": {
"type": "android.emulator",
"device": {
"avdName": "Pixel_API_28"
}
}
},
"apps": {
"android.beta.debug": {
"type": "android.apk",
"binaryPath": "android/app/build/outputs/apk/beta/debug/app-beta-debug.apk",
"build": "cd android && ./gradlew assembleBetaDebug assembleBetaDebugAndroidTest -DtestBuildType=debug && cd .."
},
"android.beta.release": {
"type": "android.apk",
"binaryPath": "android/app/build/outputs/apk/beta/release/app-beta-release.apk",
"build": "cd android && ./gradlew assembleBetaRelease assembleBetaReleaseAndroidTest -DtestBuildType=release && cd .."
}
},
"configurations": {
"android.emu.beta.debug": {
"device": "emulator",
"app": "android.beta.debug"
},
"android.emu.beta.release": {
"device": "emulator",
"app": "android.beta.release"
}
}
}
```
#### 3. Add the Native Detox dependency
> **Starting Detox 12.5.0, Detox is shipped as a precompiled `.aar`.**
> To configure Detox as a _compiling dependency_, nevertheless -- refer to the _Setting Detox up as a compiling dependency_ section at the bottom.
In your _root_ `buildscript` (i.e. `android/build.gradle`), register both `google()` _and_ detox as repository lookup points in all projects:
```groovy
// Note: add the 'allproject' section if it doesn’t exist
allprojects {
repositories {
// ...
google()
maven {
// All of Detox' artifacts are provided via the npm module
url "$rootDir/../node_modules/detox/Detox-android"
}
}
}
```
In your app’s `buildscript` (i.e. `android/app/build.gradle`) add this in `dependencies` section:
```groovy
dependencies {
// ...
androidTestImplementation('com.wix:detox:+')
}
```
also ensure that this line appears in `dependencies`:
```groovy
dependencies {
// ...
implementation 'androidx.appcompat:appcompat:1.1.0' // (check what the latest version is!)
}
```
... and add this to the `defaultConfig` subsection:
```groovy
android {
// ...
defaultConfig {
// ...
testBuildType System.getProperty('testBuildType', 'debug') // This will later be used to control the test apk build type
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
}
}
```
Please be aware that the `minSdkVersion` needs to be at least 18.
#### 4. Add Kotlin
If your project does not already support Kotlin, add the Kotlin Gradle-plugin to your `classpath` in the root build-script (i.e.`android/build.gradle`):
```groovy
buildscript {
// ...
ext.kotlinVersion = '1.3.0' // (check what the latest version is!)
dependencies {
// ...
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
}
}
```
_Note: most guides advise of defining a global `kotlinVersion` constant - as in this example, but that is not mandatory._
_**Note that Detox has been tested for version 1.1.0 of Kotlin, and higher!**_
#### 5. Create a Detox-Test Class
Detox requires a dummy implementation of a single Android-native test.
1. Add a new file to your project, under this path and name: `android/app/src/androidTest/java/com/[your.package]/DetoxTest.java`. **Double-check that the path is correct!**
1. Copy & paste the content of the equivalent file from [the detox example app for RN](https://github.com/wix/Detox/tree/master/examples/demo-react-native/android/app/src/androidTest/java/com/example/DetoxTest.java), into it. **Don’t forget to change the package name to your project’s package name!**
#### 6. Enable clear-text (unencrypted) traffic for Detox
Starting from Android SDK API level 28, Google have disabled all clear-text network traffic by default. Namely, unless explicitly configured, all of your application’s outgoing unencrypted traffic (i.e. non-TLS using HTTP rather than HTTPS) is blocked by the device.
For Detox to work, Detox test code running on the device must connect to the test-running host through its virtual localhost interface<sup>(\*)</sup> using simple HTTP traffic. Therefore, the following network-security exemption configuration must be applied --
_In an XML resource file, e.g. `android/app/src/main/res/xml/network_security_config.xml`:_
```xml
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<domain-config cleartextTrafficPermitted="true">
<domain includeSubdomains="true">10.0.2.2</domain>
<domain includeSubdomains="true">localhost</domain>
</domain-config>
</network-security-config>
```
_In the app’s `AndroidManifest.xml`_
```xml
<manifest>
<application
...
android:networkSecurityConfig="@xml/network_security_config">
</application>
</manifest>
```
> _Refer to the [Detox example app](https://github.com/wix/Detox/tree/master/examples/demo-react-native/android/app/src/main) for an example on how this is effectively implemented._
**Note: if properly configured, this in no way compromises the security settings of your app.**
For full details, refer to [Android’s security-config guide](https://developer.android.com/training/articles/security-config), and the dedicated article in the [Android developers blog](https://android-developers.googleblog.com/2016/04/protecting-against-unintentional.html).
> _(\*) 10.0.2.2 for Google emulators, 10.0.3.2 for Genymotion emulators._
#### 7. ProGuard (Minification, Obfuscation)
In apps running [minification using ProGuard](https://developer.android.com/studio/build/shrink-code), in order for Detox to work well on release builds, please enable some Detox ProGuard configuration rules by applying the custom configuration file on top of your own. Typically, this is defined using the `proguardFiles` statement in the minification-enabled build-type in your `app/build.gradle`:
```groovy
buildTypes {
// 'release' is typically the default proguard-enabled build-type
release {
minifyEnabled true
// Typical pro-guard definitions
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
// Detox-specific additions to pro-guard
proguardFile "${rootProject.projectDir}/../node_modules/detox/android/detox/proguard-rules-app.pro"
}
}
```
:warning: **Note:** In order for Detox to be able to work properly, in `proguard-rules-app.pro`, it effectively declares rules that retain most of React-Native’s code (i.e. keep it unminified, unobfuscated) in your **production** APK. Though generally speaking, this should not be an issue (as React-Native is an open-source project), there are ways around that, if it bothers you. For example, running your E2E over a build-type specifically designed to run E2E tests using Detox would do the trick -- roughly, like so (in `app/build.gradle`):
```groovy
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.release
}
releaseE2E {
initWith release
setMatchingFallbacks('release')
proguardFile "${rootProject.projectDir}/../node_modules/detox/android/detox/proguard-rules-app.pro"
}
}
```
Here we utilize Gradle’s `initWith` to easily define `releaseE2E` in a way that is identical to the `release` build-type, with the exception of considering Detox' `proguard-rules-app.pro` in the minification process.
Following the example, you would then have to build your app using `gradlew assembleReleaseE2E` rather than `gradlew assembleRelease` before running Detox, and instruct Detox (i.e. via `binaryPath` in the Detox configuration file) to use the APK resulted specifically by _that_ Gradle target (e.g. in `app/build/apk/releaseE2E/app-releaseE2E.apk` instead of the equivalent `app/build/apk/release/app-release.apk`).
> Note: if your app contains flavors -- that makes things a bit trickier, but the approach can generally be adjusted to support that as well.
**Last but not least:** If you’re having issue with Detox' ProGuard rules, please report them [here](https://github.com/wix/Detox/issues/new/choose).
A special thanks to [@GEllickson-Hover](https://github.com/GEllickson-Hover) for reporting issues related to obfuscation in [#2431](https://github.com/wix/Detox/issues/2431).
#### 8. Test Butler Support (Optional)
If, when [setting up your work environment](Introduction.AndroidDevEnv.md), you’ve selected Google emulators with an AOSP image as the test target - as recommended, **we strongly encourage** you would also integrate [Test Butler](https://github.com/linkedin/test-butler): in the very least - in order to suppress crash and ANR dialogs. They are a soft spot in UI testing on Android, all around, as - when displayed, they make the UI entirely inaccessible (and thus cause tests to fail in bulks).
Setting Test Butler up for working with Detox is a bit different than explained in their guides. The process, as a whole, is twofold:
1. Preinstalling the test-butler-app APK onto the test device.
1. Integrating the test-butler-lib into your own test APK, and initializing it in a custom test runner (as explained).
The library part can be easily achieved as explained there (i.e. by using Gradle’s `androidTestImplementation`). Same goes for initialization. As for the APK, the suggested usage of Gradle’s `androidTestUtil` is scarce when running with Detox (i.e. non-native instrumentation tests). Here’s what to do instead.
> _For a complete and thorough coverage of the Test Butler integration with Detox, consider going over our [blogpost on CI execution](https://medium.com/wix-engineering/how-to-execute-android-ui-tests-on-ci-and-stay-alive-eb9089d88c1f) on medium_.
##### Solution 1: Prebaked Images
If you have control over the emulators' snapshots, simply download (see test-butler’s guide) and install the test-butler APK once (e.g. use `adb install -r -t path/to/test-butler-app.apk`), and save an updated version of the snapshot. This is the best solution.
> Note: you will have to reiterate this if you upgrade to a newer version of Test-Butler, in the future.
##### Solution 2: Dynamic Installation
Assuming you have the APK available in the system, you can dynamically have Detox automatically install it in all of the running target-emulators by utilizing `utilBinaryPaths` in your Detox configuration. Example:
```json
{
"devices": {
"emulator.oss": {
"type": "android.emulator",
"device": "...",
"utilBinaryPaths": ["relative/path/to/test-butler-app-2.2.1.apk"],
}
}
}
```
> Refer to our [configuration guide](APIRef.Configuration.md) for further details on `utilBinaryPaths`.
As per _making_ the APK available - for that, we have no really good solution, for the time being (but it’s in the works). A few options might be:
a. In a custom script, have it predownloaded from Maven directly, as suggested in the Test Butler guide. For example (on a Mac / Linux):
```sh
curl -f -o ./temp/test-butler-app.apk https://repo1.maven.org/maven2/com/linkedin/testbutler/test-butler-app/2.2.1/test-butler-app-2.2.1.apk
```
_Jests' [global-setup](https://jestjs.io/docs/en/configuration#globalsetup-string) is a recommend place for those kinds of things._
> Should you decide to go this path, we recommend you add `./temp/test-butler-app.apk` to the relevant `.gitignore`.
b. (Discouraged) Add it to your source control (e.g. git), as part of the repository.
### Setting Detox up as a compiling dependency
This is an **alternative** to the setup process described under the previous section, on adding Detox as a dependency.
In your project’s `settings.gradle` add:
```groovy
include ':detox'
project(':detox').projectDir = new File(rootProject.projectDir, '../node_modules/detox/android/detox')
```
In your _root_ `buildscript` (i.e. `android/build.gradle`), register `google()` as a repository lookup point in all projects:
```groovy
// Note: add the 'allproject' section if it doesn’t exist
allprojects {
repositories {
// ...
google()
}
}
```
In your app’s `buildscript` (i.e. `android/app/build.gradle`) add this in `dependencies` section:
```groovy
dependencies {
// ...
androidTestImplementation(project(path: ":detox"))
}
```
In your app’s `buildscript` (i.e. `android/app/build.gradle`) add this to the `defaultConfig` subsection:
```groovy
android {
// ...
defaultConfig {
// ...
testBuildType System.getProperty('testBuildType', 'debug') // This will later be used to control the test apk build type
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
missingDimensionStrategy 'detox', 'full'
}
}
```
Please be aware that the `minSdkVersion` needs to be at least 18.
### Troubleshooting
Please refer to [troubleshooting guide about build issues](Troubleshooting.BuildingTheApp.md#android) for assistance.
-126
View File
@@ -1,126 +0,0 @@
---
id: getting-started
slug: introduction/getting-started
title: Getting Started
sidebar_label: Getting Started
---
## Getting Started
**Welcome to Detox!**
In this guide, we will walk you through setting Detox up in your project, one step at a time.
You will find that some steps are longer than the others: some are just one-paragraph long, while for others we have a dedicated multistep guide worked out. Bear with us - it is all necessary, and once set-up, it is easy to move forward with writing tests very rapidly.
## Step 1: Environment Setup
### Install [Node.js](https://nodejs.org/en/)
`Node.js` is the JavaScript runtime Detox will run on. **Install Node.js `v12.0` or above**.
There’s more than one way to install Node.js:
- Download from the [official download page](https://nodejs.org/en/download/)
- Use [Homebrew](https://formulae.brew.sh/formula/node)
- Use `nvm` - if you need to allow for several versions to be installed on a single machine
The simplest way is to use Homebrew:
```sh
brew install node
```
> Tip: Verify installation succeeded by typing in `node -v` in the terminal to output current node version.
### Install Detox Command Line Tools (`detox-cli`)
This package makes it easier to operate Detox from the command line. `detox-cli` should be installed globally, enabling usage of the command line tools outside your npm scripts. `detox-cli` is merely a script that passes commands through to a command line tool shipped inside `detox` package (in `node_modules/.bin/detox`).
```bash npm2yarn
npm install detox-cli --global
```
### Install Platform-specific Dependencies, Tools and SDKs
Depending on the platform/s you’re aiming at (iOS, Android), take the time to run through these environment setup guides:
- [Android](Introduction.AndroidDevEnv.md)
- [iOS](Introduction.iOSDevEnv.md)
## Step 2: Add Detox to Your Project
### Install the Detox Node-module
If you have a React Native project, go to its root folder (where `package.json` is found) and type the following command:
```bash npm2yarn
npm install detox --save-dev
```
If you have a project without Node integration (such as a native project), add the following `package.json` file to the root folder of your project:
```json
{
"name": "<your_project_name>",
"version": "0.0.1"
}
```
Name your project in `package.json` and then run the following command:
```bash npm2yarn
npm install detox --save-dev --no-package-lock
```
**You should now have Detox available in `node_modules/detox`**
> **Tip:** Remember to add the `node_modules` folder to your git ignore file (e.g. `.gitignore`).
### Set Up a Test Runner
Follow [our comprehensive guide for Jest](Guide.Jest.md).
### Apply Detox Configuration
If you’ve completed the test runner setup successfully using `detox init`, you should have a `.detoxrc.json` file containing a skeletal configuration for Detox to use. This configuration is only half-baked and needs to be set up properly. You now need to either create or edit that file, and apply the actual configuration suitable for your specific project.
Detox scans for a configuration through multiple files. It starts from the current working directory, and runs over the following options, in this order:
1. `.detoxrc.js`
1. `.detoxrc.json`
1. `.detoxrc`
1. `detox.config.js`
1. `detox.config.json`
1. `package.json` (`"detox"` section)
If you prefer to use something other than `.detoxrc.json`—for example, would like to keep all project configs in one place—you can create a `detox` section in your `package.json`. If you otherwise prefer separating configs, all of the other options are valid.
For specific configuration options for each supported platform, see:
- [Android](Introduction.Android.md)
- [iOS](Introduction.iOS.md)
## Step 3: Build Your App and Run Detox Tests
### 1. Build Your App
Use a convenience method in Detox command line tools to build your project easily:
```sh
detox build --configuration <your configuration name>
```
> **Note:** Detox executes the build command you specified in your Detox configuration. If your build fails, make sure to provide the correct build command.
### 2. Run the Tests
Use the Detox command line tools to test your project easily:
```sh
detox test --configuration <your configuration name>
```
That’s it. Your first failing Detox test is running!
Next, we’ll go over usage and how to make this test [actually pass](Introduction.WritingFirstTest.md).
-18
View File
@@ -1,18 +0,0 @@
---
id: workflows
slug: introduction/workflows
title: Workflows
sidebar_label: Workflows
---
## Workflows
There are multiple recommended ways to work with Detox and make it a part of your development process. Choose the best workflow for your needs:
- [Running Tests Locally on Your Machine](Guide.RunningLocally.md) — If your app is ready and does not require any active development, you can write your tests using this workflow and run them locally on your machine. This is convenient for developing your test suite without actively developing your app.
- [Developing Your App While Writing Tests](Guide.DevelopingWhileWritingTests.md) — If your app requires active development, such as adding [testID](https://facebook.github.io/react-native/docs/view.html#testid) fields for tests, this is a good workflow. It allows you to work both on your app and your tests at the same time.
- [Running Tests on CI (like Travis)](Guide.RunningOnCI.md) — When your test suite is finally ready, it should be set up to run automatically on your CI server on every git push. This will alert you if new changes to the app break existing functionality.
- [Debugging Apps in Xcode During a Test](Guide.DebuggingInXcode.md) — Advanced users might need to natively debug their app inside Xcode during a Detox test. This is mostly useful for investigating weird crashes or when contributing to Detox itself.
-71
View File
@@ -1,71 +0,0 @@
---
id: ios
slug: introduction/ios
title: Detox for iOS
sidebar_label: Detox for iOS
---
## Detox for iOS
### 1. Preliminary
Run through the basic steps of the [Getting Started guide](Introduction.GettingStarted.md), such as the environment and tools setup.
### 2. Apply Detox Configuration
Whether you’ve selected to apply the configuration in a `.detoxrc.json` or bundle it into your project’s `package.json` (under the `detox` section), this is what the configuration should roughly look like for iOS:
```json
{
"devices": {
"simulator": {
"type": "ios.simulator",
"device": {
"type": "iPhone 12 Pro Max"
}
}
},
"apps": {
"ios.release": {
"name": "YourProject",
"type": "ios.app",
"binaryPath": "ios/build/Build/Products/Release-iphonesimulator/YourProject.app",
"build": "xcodebuild -project ios/YourProject.xcodeproj -scheme YourProject -sdk iphonesimulator -derivedDataPath ios/build"
}
},
"configurations": {
"ios.sim.release": {
"device": "simulator",
"app": "ios.release"
}
}
}
```
:::info
For a comprehensive explanation of Detox configuration, see our [dedicated API-reference guide](APIRef.Configuration.md).
:::
In the above configuration example, make sure to provide the correct information for your project/app. Under the key `"binaryPath"`, you should provide the path of the .app bundle to use. Normally, this is the path where the `"build”` command would output this bundle. Under the key `"build"`, specify the `xcodebuild` command for your project.
:::tip
If your app uses CocoaPods, pass `-workspace` in your `xcodebuild` command, for example:
```json
"build": "xcodebuild -workspace ios/YourProject.xcworkspace -scheme YourProject -sdk iphonesimulator -derivedDataPath ios/build"
```
:::
:::info
For more information on using the xcodebuild command, visit [Apple Docs](https://developer.apple.com/library/archive/technotes/tn2339/_index.html#//apple_ref/doc/uid/DTS40014588-CH1-HOW_DO_I_BUILD_MY_PROJECTS_FROM_THE_COMMAND_LINE_).
:::
Also, make sure the simulator model specified under the key `device.type` (e.g. `iPhone 12 Pro Max` above) is actually available on your machine (it was installed by Xcode). Check this by typing `applesimutils --list` in Terminal to display all available simulators.
For a complete, working example, refer to the [Detox example project configuration](https://github.com/wix/Detox/blob/master/detox/test/package.json).
-42
View File
@@ -1,42 +0,0 @@
---
id: ios-dev-env
slug: introduction/ios-dev-env
title: Setting Up an iOS Development & Testing Environment
sidebar_label: Setting Up an iOS Development & Testing Environment
---
## Setting Up an iOS Development & Testing Environment
This guide sums up the tools required for an environment for running automated UI tests using iOS simulators (using Detox, in particular).
### Prerequisites
Running Detox (on iOS) requires the following:
- MacOS Catalina or newer
- Xcode `v12.x` or newer (`v13` support - see [here](https://github.com/wix/Detox/issues/2895)), with Xcode command-line tools installed
Xcode can be installed from the App Store, or downloaded [directly from Apple Developer](https://developer.apple.com/download/more/)
### Dependencies
#### Install the Latest Version of [Homebrew](http://brew.sh)
Homebrew is a package manager for macOS, used to install other command line tools.
To ensure everything needed for Homebrew tool installation is installed, run
```sh
xcode-select --install
```
#### Install [`applesimutils`](https://github.com/wix/AppleSimulatorUtils)
A collection of utils for Apple simulators, Detox uses it to query and communicate with the simulator.
```sh
brew tap wix/brew
brew install applesimutils
```
> **Note:** Make sure to periodically update your version of `applesimutils` to the latest version.
-57
View File
@@ -1,57 +0,0 @@
## Detox Documentation
### Introduction
- [Getting Started](Introduction.GettingStarted.md)
- [Setting Up an iOS Environment](Introduction.iOSDevEnv.md)
- [Setting Up an Android Development](Introduction.AndroidDevEnv.md)
- [Detox for iOS](Introduction.iOS.md)
- [Detox for Android](Introduction.Android.md)
- [Writing Your First Test](Introduction.WritingFirstTest.md)
- [How Detox Works](Introduction.HowDetoxWorks.md)
- [Detox Design Principles](Introduction.DesignPrinciples.md)
- [Workflows](Introduction.Workflows.md)
### API Reference
- [Detox Command Line Tools](APIRef.DetoxCLI.md)
- [Configuration](APIRef.Configuration.md)
- [The `detox` Object](APIRef.DetoxObjectAPI.md)
- [The `device` Object](APIRef.DeviceObjectAPI.md)
- [Test Lifecycle](APIRef.TestLifecycle.md)
- [Matchers](APIRef.Matchers.md)
- [Actions](APIRef.ActionsOnElement.md)
- [Expectations](APIRef.Expect.md)
- [Mocking Open With URL](APIRef.MockingOpenWithURL.md)
- [Mocking User Notifications](APIRef.MockingUserNotifications.md)
- [Mocking User Activity](APIRef.MockingUserActivity.md)
- [Test Artifacts](APIRef.Artifacts.md)
- [Taking Screenshots](APIRef.Screenshots.md)
### Troubleshooting
- [Table of contents](Troubleshooting.md)
- [Building the App](Troubleshooting.BuildingTheApp.md)
- [Running tests](Troubleshooting.RunningTests.md)
- [Synchronization issues](Troubleshooting.Synchronization.md)
- [General tests stability issues](Troubleshooting.Flakiness.md)
### Guides
- [Running Locally](Guide.RunningLocally.md)
- [Developing Your App While Writing Tests](Guide.DevelopingWhileWritingTests.md)
- [Running on CI](Guide.RunningOnCI.md)
- [Debugging in Xcode](Guide.DebuggingInXcode.md)
- [Debugging in Android Studio](Guide.DebuggingInAndroidStudio.md)
- [Mocking](Guide.Mocking.md)
- [Migration Between Detox Versions](Guide.Migration.md)
- [Jest Setup Guide](Guide.Jest.md)
- [Mocha Setup Guide](Guide.Mocha.md)
- [Parallel Test Execution](Guide.ParallelTestExecution.md)
- [Third-party Drivers](Guide.ThirdPartyDrivers.md)
- [Uninstalling Detox](Guide.Uninstalling.md)
- [Detox & Expo](Guide.Expo.md)
### Contributing to Detox
- [Detox Contribution Guide](Guide.Contributing.md)
+31
View File
@@ -0,0 +1,31 @@
# Artifacts
## Video Recording Issues on CI
For iOS, you might be getting errors on CI similar to this:
```plain text
Error: Error Domain=NSPOSIXErrorDomain Code=22 "Invalid argument" UserInfo={NSLocalizedDescription=Video recording requires hardware Metal capability.}.
```
Unfortunately, this error is beyond our reach. To fix it, you have to enable hardware acceleration on your build machine, or just disable video recording on CI if it is not possible to turn on the acceleration.
There might be a similar issue on Android when the screen recording process exits with an error on CI. While the solution might be identical to the one above, also you might try to experiment with other emulator devices and Android OS versions to see if it helps.
## Detox Instruments is Installed in a Custom Location
If you have to use [Detox Instruments](https://github.com/wix/DetoxInstruments) installed in a custom location, you can point Detox to it with the `DETOX_INSTRUMENTS_PATH` environment variable, as shown below:
```bash
DETOX_INSTRUMENTS_PATH="/path/to/Detox Instruments.app" detox test ...
```
> **Note:** If **Detox Instruments** had been [integrated into your project](https://github.com/wix/DetoxInstruments/blob/master/Documentation/XcodeIntegrationGuide.md), then the integrated [Detox Profiler framework](https://github.com/wix/DetoxInstruments/tree/master/Profiler) will be used when profiling with Detox.
## `Ctrl+C` Does Not Clean Up Temporary Files
This is a known issue. :man\_shrugging:
After you press `Ctrl+C` and stop the tests, some of temporary files won’t get erased (e.g. `/sdcard/83541_0.mp4` on Android emulator, or `/private/var/folders/lm/thz8hdxs4v3fppjh0fjc2twhfl_3x2/T/f12a4fcb-0d1f-4d98-866c-e7cea4942ade.png` on your Mac).
It cannot be solved on behalf of Detox itself, because the problem has to do with how Jest runner terminates its puppet processes.
The issue is on our radar, but the ETA for the fix stays unknown.
If you feel able to contribute the fix to [Jest](https://github.com/facebook/jest), you are very welcome.
+1 -1
View File
@@ -35,6 +35,6 @@ In order to identify the source of flakiness you’re suffering from you need mo
To enable `trace` mode run your tests in trace log mode:
```sh
```bash
detox test --loglevel trace
```
+5 -5
View File
@@ -30,7 +30,7 @@ For troubleshooting of other issue, refer to our [troubleshooting index](Trouble
It’s a good idea to get as much information as possible about what’s going on. We can enable trace mode during tests by running our tests with:
```sh
```bash
detox test --loglevel trace
```
@@ -44,7 +44,7 @@ In order to run tests on a simulator, you need to have simulator images installe
If you’re missing a simulator, make sure Xcode is installed and use it to download the simulator. Take a look at the Preferences screen, some screenshots can be seen [here](http://stackoverflow.com/questions/33738113/how-to-install-ios-9-1-simulator-in-xcode-version-7-1-1-7b1005).
Once the desired simulator is installed and returned by `xcrun simctl list`, double check its name in the list and make sure this name is found in the `detox` configuration entry in `package.json`. The reference for the configuration options is available [here](APIRef.Configuration.md).
Once the desired simulator is installed and returned by `xcrun simctl list`, double check its name in the list and make sure this name is found in the `detox` configuration entry in `package.json`. The reference for the configuration options is available [here](config/devices.md).
#### Tests execution hangs
@@ -60,12 +60,12 @@ This can be a result of various reasons. It is generally up to you to debug and
- You might have forgotten to run `device.launchApp()` in the beginning of your test.
- The app might have crashed before Detox has had a chance to connect to it. To get the crash details, you can run Detox tests with `--record-logs all` CLI option and then inspect the device logs in the artifacts' folder.
- **On Android**, there might be a problem with the native test code in the `DetoxTest.java` file. Revisit the [associated section](Introduction.Android.md#5-create-a-detox-test-class) in the setup guide.
- **On Android**, there might be a problem with the native test code in the `DetoxTest.java` file. Revisit the [associated section](introduction/building-with-detox.mdx#5-create-a-detox-test-class) in the setup guide.
##### If you _do_ see your app running on the device
- **On Android with SDK≥28**, the app’s connection to the Detox test server is blocked due to clear-traffic blockage (as reported in issue [#1450](https://github.com/wix/Detox/issues/1450)).
The main step for getting this fixed is to revisit the [associated section](Introduction.Android.md#6-enable-clear-text-unencrypted-traffic-for-detox) in the setup guide, which discusses network-security. Alternatively, the `android:usesCleartextTraffic="true"` attribute can be configured in the `<application>` tag of the app’s `AndroidManifest.xml`, but **that is highly discouraged**.
The main step for getting this fixed is to revisit the [associated section](introduction/building-with-detox.mdx#6-enable-clear-text-unencrypted-traffic-for-detox) in the setup guide, which discusses network-security. Alternatively, the `android:usesCleartextTraffic="true"` attribute can be configured in the `<application>` tag of the app’s `AndroidManifest.xml`, but **that is highly discouraged**.
- If you’ve applied the above suggestion but the app fails to connect to the Detox test server, nonetheless: Refer to the device’s logs, which should contain messages about failed connection attempts (get them using the `--record-logs all` argument)
- The app could be running without Detox native code injected. In this case, first, make sure you’re not trying to run in manual launch mode (where this behavior is valid). If so, examine the logs from the device (get them using the `--record-logs all` argument). If you see a crash related to Detox’s native code, you are welcome to report it on our GitHub tracker.
- If you are in fact debugging your native code integration with Detox, these guides may prove helpful:
@@ -174,7 +174,7 @@ Test Failed: View "<RCTScrollView: 0x7f8d32296d70>" is not visible: view does no
```
1. Try retrieving `ui.viewhierarchy` artifact — sometimes examining the hierarchy visually can give you insights.
Add a line `"uiHierarchy": "enabled"` to your artifacts' configuration in `.detoxrc.js`, like in an example here: [Artifacts Configuration](https://github.com/wix/Detox/blob/master/docs/APIRef.Configuration.md#artifacts-configuration). After a rerun, you should find
Add a line `"uiHierarchy": "enabled"` to your artifacts' configuration in `.detoxrc.js`, like in an example here: [Artifacts Configuration](config/artifacts.md). After a rerun, you should find
a `ui.viewhierarchy` in a folder of your failing test. Please mind that you need Xcode 12 at least to open `*.viewhierarchy` files.
1. Besides, you can rerun your iOS app tests with `--take-screenshots failing`. What will happen is, for each view that fails visibility, two images will be saved at `artifacts/<configuration-timestamp-dir>/<test name>/DETOX_VISIBILITY_<viewType>__<viewID>__SCREEN.png` (and `.../DETOX_VISIBILITY_<viewType>__<viewID>__TEST.png` folder aside) with autogenerated names, e.g. `DETOX_VISIBILITY_RCTTextView__0x7fab7660f3e0__TEST.png`:
+6 -6
View File
@@ -51,7 +51,7 @@ Interactions with the application are synchronized, meaning that they will not e
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] (in ms) to complete
```sh
```bash
detox test --debug-synchronization 500
```
@@ -75,13 +75,13 @@ See [this document](https://github.com/wix/DetoxSync/blob/master/StatusDocumenta
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
```plain text
-DTXEnableVerboseSyncSystem YES -DTXEnableVerboseSyncResources YES
```
You can then obtain this log by running the following command:
```shell
```bash
xcrun simctl spawn booted log stream --level debug --style compact --predicate "category=='SyncManager'"
```
@@ -103,7 +103,7 @@ We always have the fail-safe of turning off automatic synchronization and waitin
This makes sense only if we’re waiting too much.
##### [Controlling the entire synchronization mechanism](https://github.com/wix/detox/blob/master/docs/APIRef.DeviceObjectAPI.md#devicedisablesynchronization)
##### [Controlling the entire synchronization mechanism](api/device.md#devicedisablesynchronization)
The synchronization mechanism can be shut down using
@@ -117,7 +117,7 @@ to turn it on again use
await device.enableSynchronization();
```
##### [Controlling network synchronization](https://github.com/wix/detox/blob/master/docs/APIRef.DeviceObjectAPI.md#deviceseturlblacklisturls)
##### [Controlling network synchronization](api/device.md#deviceseturlblacklisturls)
You can skip over synchronizing on certain URLs (for long polling tasks, or websocket connections)
@@ -143,7 +143,7 @@ await device.launchApp({
#### How do we wait manually?
This makes sense only if we’re not waiting enough (or if we’ve disabled automatic synchronization). Use the `withTimeout()` API to wait until an expectation is met. The API is documented [here](APIRef.Expect.md#withtimeouttimeout).
This makes sense only if we’re not waiting enough (or if we’ve disabled automatic synchronization). Use the `withTimeout()` API to wait until an expectation is met. The API is documented [here](api/expect.md#withtimeouttimeout).
### Tweaking and fine-tuning the synchronization mechanisms
+1
View File
@@ -14,5 +14,6 @@ Issues related to building the app:
Issues related to tests execution & runtime:
- [Running tests](Troubleshooting.RunningTests.md)
- [Artifacts](Troubleshooting.Artifacts.md)
- [Synchronization issues](Troubleshooting.Synchronization.md)
- [General tests stability issues](Troubleshooting.Flakiness.md)
@@ -1,15 +1,8 @@
---
id: actions-on-element
slug: api/actions-on-element
title: Actions
sidebar_label: Actions
---
# Actions
## Actions
Detox uses [matchers](api/matchers.md) to find UI elements in your app and actions to simulate user interaction with those elements.
Detox uses [matchers](APIRef.Matchers.md) to find UI elements in your app and actions to simulate user interaction with those elements.
Use [expectations](APIRef.Expect.md) to verify element states.
Use [expectations](api/expect.md) to verify element states.
### Methods
@@ -231,7 +224,7 @@ await element(by.id('pickerView')).setColumnToValue(1, "6");
await element(by.id('pickerView')).setColumnToValue(2, "Hello World");
```
> **Note:** When working with date pickers, you should always set an explicit locale when launching your app in order to prevent flakiness from different date and time styles. See [here](APIRef.DeviceObjectAPI.md#9-languageandlocalelaunch-with-a-specific-language-andor-local-ios-only) for more information.
> **Note:** When working with date pickers, you should always set an explicit locale when launching your app in order to prevent flakiness from different date and time styles. See [here](api/device.md#9-languageandlocalelaunch-with-a-specific-language-andor-local-ios-only) for more information.
#### `setDatePickerDate(dateString, dateFormat)` iOS only
@@ -313,7 +306,7 @@ jestExpect(multipleMatchedElements.elements[0].identifier).toBe('FirstElement');
#### `takeScreenshot(name)`
Takes a screenshot of the matched element. For full details on taking screenshots with Detox, refer to the [screenshots guide](APIRef.Screenshots.md).
Takes a screenshot of the matched element. For full details on taking screenshots with Detox, refer to the [screenshots guide](../guide/taking-screenshots.md).
`name`—the name of the screenshot
@@ -1,11 +1,4 @@
---
id: detox-cli
slug: api/detox-cli
title: Detox Command Line Tools
sidebar_label: Detox Command Line Tools
---
## Detox Command Line Tools (detox-cli)
# Command Line Tools
`detox-cli` lets you operate Detox from command line.
@@ -19,7 +12,7 @@ npm install detox-cli --global
### Usage
```sh
```bash
detox <command> [options]
```
@@ -67,14 +60,53 @@ Run the command defined in `build` property of the specified **configuration**.
| -s, --silent | Do not fail with error if an app config has no build command. |
| --help | Show help |
#### test
##### Examples
Initiating your test suite[^1].
If you have only one configuration, you can simply use:
```bash
detox build
```
To choose a specific configuration:
```bash
detox build --configuration yourConfiguration
```
To skip building an app if it already is built:
```bash
detox build --configuration yourConfiguration --if-missing
```
#### test
`detox test [options] <...testFilePaths>`
For the most part, `detox test` is a convenience method which converts CLI arguments to environment variables and
runs a third-party test runner one or multiple times (if `--retries` configured). All unknown flags are just
forwarded as-is to the test runner underneath, e.g.:
```plain text
detox test -c ios.debug --showConfig
↓
DETOX_CONFIGURATION=ios.debug jest --showConfig
```
You can freely take the CLI command it prints and run it independently, without the help of Detox CLI.
If there is a name conflict for some option (both the test runner and `detox test` have a CLI argument with the same
name), you can pass it explicitly after the reserved `--` sequence:
```plain text
detox test -c ios.debug -- --help
↓
DETOX_CONFIGURATION=ios.debug jest --help
```
| Option | Description |
| --------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| --------------------------------------------- |-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| -C, --config-path `<configPath>` | Specify Detox config file path. If not supplied, detox searches for .detoxrc\[.js] or "detox" section in package.json |
| -c, --configuration `<device config>` | Select a device configuration from your defined configurations, if not supplied, and there’s only one configuration, detox will default to it |
| -n, --device-name \[name] | Override the device name specified in a configuration. Useful for running a single build configuration on multiple devices. |
@@ -86,17 +118,17 @@ Initiating your test suite[^1].
| --record-videos \[failing/all/none] | Save screen recordings of each test to artifacts directory. Pass "failing" to save recordings of failing tests only. The default value is **none**. |
| --record-performance \[all/none] | \[iOS Only] Save Detox Instruments performance recordings of each test to artifacts directory. The default value is **none**. |
| --capture-view-hierarchy \[enabled/disabled] | \[iOS Only] Capture `*.uihierarchy` snapshots on view action errors and `device.captureViewHierarchy()` calls. The default value is **disabled**. |
| -R, --retries | Re-spawn the test runner for individual failing suite files until they pass, or `<N>` times at most. |
| -R, --retries | Re-spawn the test runner for individual failing suite files until they pass, or `<N>` times at most. |
| -r, --reuse | Reuse existing installed app (do not delete + reinstall) for a faster run. |
| -u, --cleanup | Shutdown simulator when test is over, useful for CI scripts, to make sure detox exists cleanly with no residue |
| --jest-report-specs | \[Jest Only] Whether to output logs per each running spec, in real-time. By default, disabled with multiple workers. |
| -H, --headless | Launch device in headless mode. Useful when running on CI. |
| --device-launch-args | A list of passthrough-arguments to use when (if) devices (Android emulator / iOS simulator) are launched by Detox.<br />**Note: the value must be specified after an equal sign (`=`) and inside quotes.** Usage example:<br />`--device-launch-args="-http-proxy http://1.1.1.1:8000 -no-snapshot-load"` |
| --app-launch-args | Custom arguments to pass (through) onto the app every time it is launched. The same **note** applies here, as for **--device-launch-args**.<br />See [launch arguments guide](APIRef.LaunchArgs.md) for complete info. |
| --app-launch-args | Custom arguments to pass (through) onto the app every time it is launched. The same **note** applies here, as for **--device-launch-args**.<br />See [launch arguments guide](../Guide.LaunchArgs.md) for complete info. |
| --no-color | Disable colors in log output |
| --use-custom-logger | Use Detox' custom console-logging implementation, for logging Detox (non-device) logs. Disabling will fallback to node.js / test runner’s implementation (e.g. Jest).<br />_Default: true_ |
| --gpu | \[Android Only] Launch Emulator with the specific -gpu \[gpu mode] parameter. |
| --force-adb-install | \[Android Only] Due to problems with the `adb install` command on Android, Detox resorts to a different scheme for installing APKs. Setting true will disable that and force usage of `adb install`, instead.<br/>This flag is temporary until the Detox way proves stable.<br/>_Default: false_ |
| --force-adb-install | \[Android Only] Due to problems with the `adb install` command on Android, Detox resorts to a different scheme for installing APKs. Setting true will disable that and force usage of `adb install`, instead.<br/>This flag is temporary until the Detox way proves stable.<br/>_Default: false_ |
| --inspect-brk | Uses [node’s --inspect-brk](https://nodejs.org/en/docs/guides/debugging-getting-started/#enable-inspector) flag to let users debug the test runner <br />_Default: false_ |
| --help | Show help |
@@ -111,7 +143,7 @@ rerunning it again.
> export DETOX_ARGV_OVERRIDE="--forceExit -w 1 --testNamePattern='that hanging test' e2e/sanity/login.test.js"
> bash scripts/ci.e2e.sh
# ... some output ...
> detox test -c ios.sim.release -l verbose --workers 3
> detox test -c ios.sim.release -l verbose --maxWorkers 3
# ...
configuration=ios.sim.release ... jest --maxWorkers 1 --forceExit --testNamePattern='that hanging test' e2e/sanity/login.test.js
```
@@ -147,17 +179,8 @@ If you have installed [Detox Recorder](https://github.com/wix/DetoxRecorder) in
Detox stores a cached version of its framework in `~/Library/Detox`. A different cache folder is used for different Xcode and Detox versions. Use the various cache commands to clean or build this cache.
[^1]: It should be noted that `detox test` is a convenience method to trigger an execution
of a supported test runner, so for the most part it reads configuration from CLI args and `package.json` and remaps it
to command-line arguments or environment variables that are supported by (or not conflict with) the test runner.
Hence, **extra arguments to** `detox test` **will be forwarded to your test runner**, e.g:\
1\. You run `detox test --bail`, and since `--bail` is an unknown option, it will be forwarded to the test runner as-is.\
2\. If there is a name conflict for some option (between the test runner and `detox test`), you can pass it explicitly\
after the reserved `--` sequence. For instance, `detox test -- --help`, will pass `--help` to the test runner CLI
itself.
[^2]: If `--artifacts-location` path does not end with a slash (`/`) or a backslash, then detox CLI will append to the
path a subdirectory with configuration name and timestamp (e.g. `artifacts/android.emu.release.2018-06-12 05:52:43Z`).
In other words, the path with a slash at the end assumes you do not want a subdirectory inside.
For more details, please check the [Enabling artifacts](APIRef.Artifacts.md#artifacts).
For more details, please check the [Enabling artifacts](../config/artifacts.md#artifacts).
The default value is **artifacts** (plus a subdirectory).
@@ -1,35 +1,36 @@
---
id: device-object-api
slug: api/device-object-api
title: Device Object API
sidebar_label: The `device` Object
---
# Device
## The `device` Object
The `device` object is globally available in every test file, unless you use `exposeGlobals: false` in the behavior config,
and even then you can import it from Detox package:
`device` is globally available in every test file, it enables control over the current attached device (currently only simulators are supported).
```javascript
const { device } = require('detox');
```
### Public Properties
It enables control over the current attached device.
## Public Properties
- [`device.id`](#deviceid)
- [`device.name`](#devicename)
- [`device.appLaunchArgs`](#deviceapplaunchargs)
#### `device.id`
### `device.id`
Holds the environment-unique ID of the device - namely, the `adb` ID on Android (e.g. `emulator-5554`) and the Mac-global simulator UDID on iOS, as used by `simctl` (e.g. `AAAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEEE`).
The value will be `undefined` until the device is properly _prepared_ (i.e. in `detox.init()`).
#### `device.name`
### `device.name`
Holds a descriptive name of the device. Example: `emulator-5554 (Pixel_API_26)`
The value will be `undefined` until the device is properly _prepared_ (i.e. in `detox.init()`).
#### `device.appLaunchArgs`
### `device.appLaunchArgs`
Access the launch-arguments predefined by the user in preliminary, static scopes such as the Detox [configuration file](APIRef.Configuration.md) and [command-line arguments](APIRef.DetoxCLI.md). This access allows, through dedicated methods, for both value-querying and modification:
Access the launch-arguments predefined by the user in preliminary, static scopes such as the Detox [configuration file](../config/apps.md)
and [command-line arguments](detox-cli.md). This access allows, through dedicated methods, for both value-querying and modification:
```js
// Modify some of the predefined arguments:
@@ -61,9 +62,9 @@ device.appLaunchArgs.shared.reset();
device.appLaunchArgs.get(); // ==> {}
```
This is the most flexible way of editing the launch arguments. Refer to the [launch arguments guide](APIRef.LaunchArgs.md) for complete details.
This is the most flexible way of editing the launch arguments. Refer to the [launch arguments guide](../Guide.LaunchArgs.md) for complete details.
### Methods
## Methods
- [`device.selectApp(name)`](#deviceselectappname)
- [`device.launchApp(params)`](#devicelaunchappparams)
@@ -98,10 +99,10 @@ This is the most flexible way of editing the launch arguments. Refer to the [lau
- [`device.pressBack()` **Android Only**](#devicepressback-android-only)
- [`device.getUiDevice()` **Android Only**](#devicegetuidevice-android-only)
#### `device.selectApp(name)`
### `device.selectApp(name)`
Use **only for advanced multi-app configs** when you need to switch between your apps
within the same test scenario. Refer to the [configuration doc](APIRef.Configuration.md#apps-configurations)
within the same test scenario. Refer to the [configuration doc](../config/apps.md)
to discover how to define multiple apps with different `name`s.
```js
@@ -111,13 +112,13 @@ await device.selectApp('myAppName');
As a side effect (due to the current architectural limitation) running `device.selectApp` terminates the previous
app that had been running before.
#### `device.launchApp(params)`
### `device.launchApp(params)`
Launch the app defined in the current [`configuration`](APIRef.Configuration.md#apps-configurations).
Launch the app defined in the current [`configuration`](../config/overview.md).
`params`—object, containing one of more of the following keys and values:
##### 1. `newInstance`—Launching a New Instance of the App
#### 1. `newInstance`—Launching a New Instance of the App
Terminate the app and launch it again.
@@ -127,7 +128,7 @@ If set to `false`, the device will try to resume the app (e.g. bring from foregr
await device.launchApp({newInstance: true});
```
##### 2. `permissions`—Set Runtime Permissions (iOS Only)
#### 2. `permissions`—Set Runtime Permissions (iOS Only)
Grants or denies runtime permissions to your application. This will cause the app to terminate before permissions are applied.
@@ -137,7 +138,7 @@ await device.launchApp({permissions: {calendar: 'YES'}});
Detox uses [AppleSimUtils](https://github.com/wix/AppleSimulatorUtils) to implement this functionality for iOS simulators. Read about the different types of permissions and how to set them in AppleSimUtils' documentation and by checking out Detox’s [own test suite](https://github.com/wix/Detox/tree/a9a09246c05733f6b91cfcc0dba05a4714abca92/detox/test/e2e/13.permissions.test.js).
##### 3. `url`—Launching with URL
#### 3. `url`—Launching with URL
Launches the app with the specified URL to test your app’s deep link handling mechanism.
@@ -147,9 +148,9 @@ await device.launchApp({url, newInstance: true}); // Launch a new instance of th
await device.launchApp({url, newInstance: false}); // Reuse existing instance
```
Read more [here](APIRef.MockingOpenWithURL.md). Go back to subsection 1 to read about the full effect of the `newInstance` argument.
Read more [here](../Guide.MockingOpenWithURL.md). Go back to subsection 1 to read about the full effect of the `newInstance` argument.
##### 4. `userNotification`—Launching with User Notifications
#### 4. `userNotification`—Launching with User Notifications
Launches with the specified user notification.
@@ -159,9 +160,9 @@ await device.launchApp({userNotification, newInstance: true}); // Launch a new i
await device.launchApp({userNotification, newInstance: false}); // Reuse existing instance
```
Read more [here](APIRef.MockingUserNotifications.md). Go back to subsection 1 to read about the full effect of the `newInstance` argument.
Read more [here](../Guide.MockingUserNotifications.md). Go back to subsection 1 to read about the full effect of the `newInstance` argument.
##### 5. `userActivity`—Launch with User Activity (iOS Only)
#### 5. `userActivity`—Launch with User Activity (iOS Only)
Launches the app with the specified user activity.
@@ -171,9 +172,9 @@ await device.launchApp({userActivity: activity, newInstance: true}); //Launch a
await device.launchApp({userActivity: activity, newInstance: false}); //Reuse existing instance
```
Read more in [here](APIRef.MockingUserActivity.md). Go back to subsection 1 to read about the full effect of the `newInstance` argument.
Read more in [here](../Guide.MockingUserActivity.md). Go back to subsection 1 to read about the full effect of the `newInstance` argument.
##### 6. `delete`—Delete and Reinstall Application Before Launching
#### 6. `delete`—Delete and Reinstall Application Before Launching
Before launching the application, it is uninstalled and then reinstalled.
@@ -183,7 +184,7 @@ A flag that enables relaunching into a fresh installation of the app (it will un
await device.launchApp({delete: true});
```
##### 7. `launchArgs`—Additional Process Launch Arguments
#### 7. `launchArgs`—Additional Process Launch Arguments
Launches the app on the device with on-site, user-specified launch arguments:
@@ -196,9 +197,9 @@ await device.launchApp({
});
```
This is the most explicit and straightforward way of setting launch arguments. Refer to the [launch arguments guide](APIRef.LaunchArgs.md) for a complete overview on app launch arguments.
This is the most explicit and straightforward way of setting launch arguments. Refer to the [launch arguments guide](../Guide.LaunchArgs.md) for a complete overview on app launch arguments.
##### 8. `disableTouchIndicators`—Disable Touch Indicators (iOS Only)
#### 8. `disableTouchIndicators`—Disable Touch Indicators (iOS Only)
Disables touch indicators on iOS. Default is `false`.
@@ -206,7 +207,7 @@ Disables touch indicators on iOS. Default is `false`.
await device.launchApp({disableTouchIndicators: true});
```
##### 9. `languageAndLocale`—Launch with a Specific Language and/or Local (iOS Only)
#### 9. `languageAndLocale`—Launch with a Specific Language and/or Local (iOS Only)
Launch the app with a specific system language
@@ -239,18 +240,18 @@ With this API, you can run sets of E2E tests per language. For example:
it('Test A', () => {
})
it('Test B', () => {
})
});
});
```
##### 10. `detoxEnableSynchronization`—Initialize Detox with synchronization enabled or disabled at app launch
#### 10. `detoxEnableSynchronization`—Initialize Detox with synchronization enabled or disabled at app launch
Launches the app with the synchronization mechanism enabled or disabled. Useful if the app cannot be synchronized during the launch process. Synchronization can later be enabled using `device.enableSynchronization()`.
@@ -258,10 +259,10 @@ Launches the app with the synchronization mechanism enabled or disabled. Useful
await device.launchApp({
newInstance: true,
launchArgs: { detoxEnableSynchronization: 0 }
});
});
```
##### 11. `detoxURLBlacklistRegex`—Initialize the URL Blacklist at app launch
#### 11. `detoxURLBlacklistRegex`—Initialize the URL Blacklist at app launch
Launches the app with a URL blacklist to disable network synchronization on certain endpoints. Useful if the app makes frequent network calls to blacklisted endpoints upon startup.
@@ -272,13 +273,13 @@ await device.launchApp({
});
```
#### `device.relaunchApp(params)`
### `device.relaunchApp(params)`
The method calls `launchApp({newInstance: true})` as a convenience method.
#### `device.terminateApp()`
### `device.terminateApp()`
By default, `terminateApp()` with no params will terminate the app file defined in the current [`configuration`](APIRef.Configuration.md).
By default, `terminateApp()` with no params will terminate the app file defined in the current [`configuration`](config/overview.md).
To terminate another app, specify its bundle id
@@ -286,7 +287,7 @@ To terminate another app, specify its bundle id
await device.terminateApp('other.bundle.id');
```
#### `device.sendToHome()`
### `device.sendToHome()`
Send application to background by bringing `com.apple.springboard` to the foreground.
Combining `sendToHome()` with `launchApp({newInstance: false})` will simulate app coming back from background.
@@ -300,15 +301,15 @@ await device.launchApp({newInstance: false});
Check out Detox’s [own test suite](https://github.com/wix/Detox/tree/a9a09246c05733f6b91cfcc0dba05a4714abca92/detox/test/e2e/06.device.test.js)
#### `device.reloadReactNative()`
### `device.reloadReactNative()`
If this is a React Native app, reload the React Native JS bundle. This action is much faster than `device.launchApp()`, and can be used if you just need to reset your React Native logic.
<i>**Note:** This functionality does not work without faults. Under certain conditions, the system may not behave as expected and/or even crash. In these cases, use `device.launchApp()` to launch the app cleanly instead of only reloading the JS bundle.</i>
#### `device.installApp()`
### `device.installApp()`
By default, `installApp()` with no params will install the app file defined in the current [`configuration`](APIRef.Configuration.md).
By default, `installApp()` with no params will install the app file defined in the current [`configuration`](config/overview.md).
To install another app, specify its path
@@ -316,9 +317,9 @@ To install another app, specify its path
await device.installApp('path/to/other/app');
```
#### `device.uninstallApp()`
### `device.uninstallApp()`
By default, `uninstallApp()` with no params will uninstall the app defined in the current [`configuration`](APIRef.Configuration.md).
By default, `uninstallApp()` with no params will uninstall the app defined in the current [`configuration`](config/overview.md).
To uninstall another app, specify its bundle id
@@ -326,27 +327,27 @@ To uninstall another app, specify its bundle id
await device.uninstallApp('other.bundle.id');
```
#### `device.openURL({url, sourceApp[optional]})`
### `device.openURL({url, sourceApp[optional]})`
Mock opening the app from URL. `sourceApp` is an optional **iOS-only** parameter to specify source application bundle id.
Read more in [Mocking Open with URL](APIRef.MockingOpenWithURL.md) section.
Read more in [Mocking Open with URL](../Guide.MockingOpenWithURL.md) section.
Check out Detox’s [own test suite](https://github.com/wix/Detox/tree/a9a09246c05733f6b91cfcc0dba05a4714abca92/detox/test/e2e/15.urls.test.js)
#### `device.sendUserNotification(params)`
### `device.sendUserNotification(params)`
Mock handling of a user notification previously received in the system, while the app is already running.
Read more in [Mocking User Notifications](APIRef.MockingUserNotifications.md) section.
Read more in [Mocking User Notifications](../Guide.MockingUserNotifications.md) section.
Check out Detox’s [own test suite](https://github.com/wix/Detox/tree/a9a09246c05733f6b91cfcc0dba05a4714abca92/detox/test/e2e/11.user-notifications.test.js)
#### `device.sendUserActivity(params)` **iOS Only**
### `device.sendUserActivity(params)` **iOS Only**
Mock handling of received user activity when app is in foreground.
Read more in [Mocking User Activity](APIRef.MockingUserActivity.md) section.
Read more in [Mocking User Activity](../Guide.MockingUserActivity.md) section.
Check out Detox’s [own test suite](https://github.com/wix/Detox/tree/a9a09246c05733f6b91cfcc0dba05a4714abca92/detox/test/e2e/18.user-activities.test.js)
#### `device.setOrientation(orientation)`
### `device.setOrientation(orientation)`
Takes `"portrait"` or `"landscape"` and rotates the device to the given orientation.
@@ -354,7 +355,7 @@ Takes `"portrait"` or `"landscape"` and rotates the device to the given orientat
Check out Detox’s [own test suite.](https://github.com/wix/Detox/tree/a9a09246c05733f6b91cfcc0dba05a4714abca92/detox/test/e2e/06.device-orientation.test.js)
#### `device.setLocation(lat, lon)`
### `device.setLocation(lat, lon)`
Sets the simulator/emulator location to the given latitude and longitude.
@@ -366,7 +367,7 @@ Sets the simulator/emulator location to the given latitude and longitude.
await device.setLocation(32.0853, 34.7818);
```
#### `device.disableSynchronization()`
### `device.disableSynchronization()`
Temporarily disable synchronization (idle/busy monitoring) with the app - namely, stop waiting for the app to go idle before moving forward in the test execution.
@@ -379,7 +380,7 @@ Note: Synchronization is enabled by default, and it gets **re-enabled on every l
await device.disableSynchronization();
```
#### `device.enableSynchronization()`
### `device.enableSynchronization()`
Re-enable synchronization (idle/busy monitoring) with the app - namely, resume waiting for the app to go idle before moving forward in the test execution, after a previous disabling of it through a call to `device.disableSynchronization()`.
@@ -389,15 +390,15 @@ Re-enable synchronization (idle/busy monitoring) with the app - namely, resume w
await device.enableSynchronization();
```
#### `device.setURLBlacklist([urls])`
### `device.setURLBlacklist([urls])`
Exclude synchronization with respect to network activity (i.e. don’t wait for network to go idle before moving forward in the test execution) according to **specific** endpoints, denoted as URL reg-exp’s. To disable endpoints at initialization, pass in the black-list as an [app-launch argument](APIRef.LaunchArgs.md) named `detoxURLBlacklistRegex` (as explained [here](#11-detoxurlblacklistregexinitialize-the-url-blacklist-at-app-launch)).
Exclude synchronization with respect to network activity (i.e. don’t wait for network to go idle before moving forward in the test execution) according to **specific** endpoints, denoted as URL reg-exp’s. To disable endpoints at initialization, pass in the black-list as an [app-launch argument](../Guide.LaunchArgs.md) named `detoxURLBlacklistRegex` (as explained [here](#11-detoxurlblacklistregexinitialize-the-url-blacklist-at-app-launch)).
```js
await device.setURLBlacklist(['.*127.0.0.1.*', '.*my.ignored.endpoint.*']);
```
#### `device.resetContentAndSettings()` **iOS Only**
### `device.resetContentAndSettings()` **iOS Only**
Resets the Simulator to clean state (like the Simulator > Reset Content and Settings... menu item), especially removing
previously set permissions.
@@ -406,7 +407,7 @@ previously set permissions.
await device.resetContentAndSettings();
```
#### `device.getPlatform()`
### `device.getPlatform()`
Returns the current device, `ios` or `android`.
@@ -416,11 +417,11 @@ if (device.getPlatform() === 'ios') {
}
```
#### `device.takeScreenshot([name])`
### `device.takeScreenshot([name])`
Takes a screenshot of the device. For full details on taking screenshots with Detox, refer to the [screen-shots guide](APIRef.Screenshots.md).
Takes a screenshot of the device. For full details on taking screenshots with Detox, refer to the [screen-shots guide](../guide/taking-screenshots.md).
#### `device.captureViewHierarchy([name])`
### `device.captureViewHierarchy([name])`
**iOS Only.** Saves a view hierarchy snapshot (`*.viewhierarchy`) of the
currently opened application to a temporary folder and schedules putting it to
@@ -442,11 +443,11 @@ test('Capture view hierarchy', async () => {
});
```
#### `device.shake()` **iOS Only**
### `device.shake()` **iOS Only**
Simulate shake
#### `device.setBiometricEnrollment(bool)` **iOS Only**
### `device.setBiometricEnrollment(bool)` **iOS Only**
Toggles device enrollment in biometric authentication (Touch ID or Face ID).
@@ -456,27 +457,27 @@ await device.setBiometricEnrollment(true);
await device.setBiometricEnrollment(false);
```
#### `device.matchFace()` **iOS Only**
### `device.matchFace()` **iOS Only**
Simulates the success of a face match via Face ID
#### `device.unmatchFace()` **iOS Only**
### `device.unmatchFace()` **iOS Only**
Simulates the failure of face match via Face ID
#### `device.matchFinger()` **iOS Only**
### `device.matchFinger()` **iOS Only**
Simulates the success of a finger match via Touch ID
#### `device.unmatchFinger()` **iOS Only**
### `device.unmatchFinger()` **iOS Only**
Simulates the failure of a finger match via Touch ID
#### `device.clearKeychain()` **iOS Only**
### `device.clearKeychain()` **iOS Only**
Clears the device keychain
#### `device.setStatusBar()` **iOS Only**
### `device.setStatusBar()` **iOS Only**
Override simulator’s status bar. Available options:
@@ -502,19 +503,19 @@ await device.setStatusBar({
});
```
#### `device.resetStatusBar()` **iOS Only**
### `device.resetStatusBar()` **iOS Only**
Resets any override in simulator’s status bar.
#### `device.reverseTcpPort()` **Android Only**
### `device.reverseTcpPort()` **Android Only**
Reverse a TCP port from the device (guest) back to the host-computer, as typically done with the `adb reverse` command. The end result would be that all network requests going from the device to the specified port will be forwarded to the computer.
#### `device.unreverseTcpPort()` **Android Only**
### `device.unreverseTcpPort()` **Android Only**
Clear a _reversed_ TCP-port (e.g. previously set using `device.reverseTcpPort()`).
#### `device.pressBack()` **Android Only**
### `device.pressBack()` **Android Only**
Simulate press back button.
@@ -522,7 +523,7 @@ Simulate press back button.
await device.pressBack();
```
#### `device.getUiDevice()` **Android Only**
### `device.getUiDevice()` **Android Only**
Exposes [`UiAutomator`’s `UiDevice` API](https://developer.android.com/reference/androidx/test/uiautomator/UiDevice).
**This is not a part of the official Detox API**, it may break and change whenever an update to `UiDevice` or `UiAutomator` Gradle dependencies (`androidx.test.uiautomator:uiautomator`) is introduced.
+3 -10
View File
@@ -1,15 +1,8 @@
---
id: expect
slug: api/expect
title: Expect
sidebar_label: Expect
---
# Expect
## Expect
Detox uses [matchers](api/matchers.md) to match UI elements in your app and expectations to verify those elements are in the expected state.
Detox uses [matchers](APIRef.Matchers.md) to match UI elements in your app and expectations to verify those elements are in the expected state.
Use [actions](APIRef.ActionsOnElement.md) to simulate use interaction with elements.
Use [actions](api/actions.md) to simulate use interaction with elements.
### Methods
+105
View File
@@ -0,0 +1,105 @@
# Internals
:::caution
This section might be more volatile than the other ones, yet we'll do our
best to adhere to Semantic Release standards even here.
:::
Detox Internals might be useful for developing advanced enterprise presets
or if you are planning to integrate with a third-party test runner like
[Mocha], [Ava], [Vitest] or other ones.
## Main lifecycle
### resolveConfig
Use with a caution, when you still have no config, yet need to avoid \[internals.init()]\[#init] call.
You normally don't need it if you use Detox CLI (`detox test …`), but if you want to start tests
directly and you need to have the config resolved before \[internals.init()]\[#init] is called, this
is the way to go.
### getStatus
Returns a string (`inactive`, `init`, `active` or `cleanup`) depending on what's going on.
### init
This is the phase where Detox reads its configuration, starts a server.
### cleanup
The global cleanup phase should happen after all the tests have finished.
This is the phase where the Detox server shuts down.
### installWorker
This is the phase where Detox loads its expectation library and starts a device.
### uninstallWorker
Deallocates the device.
## Optional lifecycle
### Synchronizing with artifacts manager
The naming you can see adheres much to Jest Circus workflow:
- onRunStart
- onRunDescribeStart
- onTestStart
- onHookStart
- onHookFailure
- onHookSuccess
- onTestFnStart
- onTestFnFailure
- onTestFnSuccess
- onTestDone
- onRunDescribeFinish
- onRunFinish
### Reporting failed tests
`reportFailedTests` reports to Detox CLI about failed tests that could
have been re-run if `--retries` is set to a non-zero.
It takes two arguments:
- `testFilePaths` – array of failed test files' paths
- `permanent` – whether the failure is permanent, and the tests should not be re-run.
- returns a promise.
## Properties
### config
### session
### log
### tracing.createEventStream()
Creates a readable stream of the currently recorded events in
[Chrome Trace Event format](https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU).
See also: [DurationBeginEvent], [DurationEndEvent], [InstantEvent].
### worker
Not documented on purpose. Provides the direct access to the object which
holds the device driver, websocket client, matchers, expectations, etc.
[Mocha]: https://mochajs.org
[Ava]: https://github.com/avajs/ava
[Vitest]: https://vitest.dev
[DurationBeginEvent]: https://wix-incubator.github.io/trace-event-lib/interfaces/DurationBeginEvent.html
[DurationEndEvent]: https://wix-incubator.github.io/trace-event-lib/interfaces/DurationEndEvent.html
[InstantEvent]: https://wix-incubator.github.io/trace-event-lib/interfaces/InstantEvent.html
+52
View File
@@ -0,0 +1,52 @@
# Logger
TODO: rewrite this document
## Methods
- [`detox.traceCall()`](#detoxtracecall)
- [`detox.trace.startSection(), detox.trace.endSection()`](#detoxtracestartsection-detoxtraceendsection)
```js
it('Verify sanity things', async () => {
try {
detox.trace.startSection('Turn off notifications');
await element(by.id('gotoNotifications')).tap();
await element(by.id('notificationsToggle')).tap();
await device.pressBack();
} finally {
detox.trace.endSection('Turn off notifications');
}
});
```
Effectively, `start` and `end` can even be called in two complete different places - such as a `before` and an `after`. But that is discouraged. In fact, **usage of `detox.traceCall()` is the recommended way of tracing things, altogether.**
### Timeline Plugin
When enabled using the `--record-timeline all` argument to Detox, the time-line of the entire testing session is recorded, based on trace calls made by Detox internally, and explicit calls made in user test-code, combined.
The final outcome is a JSON-like file named `detox.trace.json`, which, if loaded into a Chrome-browser tab with the `chrome://tracing` URL, would look something like this:
![Timeline artifact example](../img/timeline-artifact.png)
This _tracing_ view provides a visual, hierarchical representation of the various processes that took place during the execution of the testing session, over the execution’s _time-line_. These processes appear as hierarchical _sections_ – sometimes visually ordered in a parent-child way, depending on their formation time and context.
To name a few predefined events, which are generated by Detox itself:
- **`detoxInit`:** Initialization of Detox, prior to running the suites associated with a specific tests file.
- **`awaitBoot`:** Waiting for an emulator to complete booting (thus being ready to run tests). Done in the surrounding context of `detoxInit` (and hence visually appears "below" it), as waiting for emulators' boot is an inherent part of Detox' initialization.
- **`appInstall`**, **`appUninstall`**.
- **"Sanity":** Execution of a user test suite called _Sanity_.
- **`reloadRN`:** A dynamic reload of the React-Native. Bound to calls to `device.reloadReactNative()`, specifically.
In the above example, the following can be observed:
1. There were 2 test workers (the Worker #⁠1, Worker #⁠2 time-lines) executing a total of two test suites.
1. There were 2 Android emulators used for running the test session, namely `emulator-17800` and `emulator-12466`. They were used by worker 1 and worker 2, respectively.
1. It took about a total of 54 seconds to initialize and run all the tests.
1. The first worker took longer to initialize (as depicted by the `detoxInit` section). In particular, that happened because it took longer for the associated emulator too finish bootstrapping (see the child `awaitBoot` section). That suggests there might be a problem with the test execution environment.
### Purpose
**This artifact can be helpful in looking up ways to optimize the execution of your E2E tests.** It may surface shortcomings in the test environment’s ability to run the test, or provide a means to consider different ways of splitting up your tests over test files so as to better utilize parallelism.
The artifact can in fact be even better utilized – to the level of inspecting the inside of your tests, by explicitly calling `trace` via the `detox.traceCall()` and `detox.trace.startSection()`, `detox.trace.endSection()` [APIs](#detoxtracecall) inside your tests.
@@ -1,15 +1,8 @@
---
id: matchers
slug: api/matchers
title: Matchers
sidebar_label: Matchers
---
# Matchers
## Matchers
Detox uses [matchers](api/matchers.md) to match UI elements in your app.
Detox uses [matchers](APIRef.Matchers.md) to match UI elements in your app.
Use [actions](APIRef.ActionsOnElement.md) to simulate use interaction with elements and [expectations](APIRef.Expect.md) to verify element states.
Use [actions](api/actions.md) to simulate use interaction with elements and [expectations](api/expect.md) to verify element states.
**Note:** For best results, it is recommended to match elements by unique identifiers. Matching by text or labels can introduce test flakiness when your app’s text change or when changing your app’s localization.
@@ -1,11 +1,4 @@
---
id: design-principles
slug: introduction/design-principles
title: Design Principles
sidebar_label: Design Principles
---
## Design Principles
# Design Principles
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.
@@ -1,11 +1,4 @@
---
id: how-detox-works
slug: introduction/how-detox-works
title: How Detox Works
sidebar_label: How Detox Works
---
## How Detox Works
# How Detox Works
Detox is an end-to-end testing framework. This means it runs your app on an actual device/simulator and interacts with it just like a real user would. This type of testing can give a lot of confidence in your app and help automate a manual QA process.
@@ -19,7 +12,7 @@ The two parts are usually running in separate processes on your machine. It is a
In practice, to make the communication more resilient, both parts are implemented as clients and communicate with a Detox server that acts as proxy. This allows some nice behaviors like allowing one side to disconnect (during a simulator boot for example or app restart) without disconnecting the other side and losing its state.
### How Detox Automatically Synchronizes With Your App
## How Detox Automatically Synchronizes With Your App
One of the key features of Detox is its ability to automatically synchronize the test execution with your app. The most annoying aspect of end-to-end tests is flakiness—tests sometimes fail without anything changing. Flakiness happens because tests are nondeterministic. Every time a test is running, things take place in a slightly different order inside your app.
@@ -34,7 +27,7 @@ Detox tries to eliminate flakiness by automatically synchronizing your tests wit
- Keeping track of timers and waiting until they expire or are cancelled
- Keeping track of the React Native operations
### Architecture
## Architecture
Detox comprises the following components:
@@ -1,11 +1,4 @@
---
id: third-party-drivers
slug: guide/third-party-drivers
title: Third-Party Drivers
sidebar_label: Third-Party Drivers
---
## Third-Party Drivers
# Third-Party Drivers
Detox comes with built-in support for running on Android and iOS by choosing a driver type in your Detox configurations.
For example, the following configuration uses the "ios.simulator" driver.
@@ -52,7 +45,7 @@ Overall the setup for any third party driver is fairly simple.
1. Run Detox while specifying the name of your new configuration:
```sh
```bash
detox test --configuration thirdparty.driver.config
```
@@ -60,11 +53,11 @@ Overall the setup for any third party driver is fairly simple.
#### Anatomy of the Drivers
The architecture of a driver is split into a few different pieces; Understanding the [overall architecture of Detox](Introduction.HowDetoxWorks.md#Architecture) will help with this section.
The architecture of a driver is split into a few different pieces; Understanding the [overall architecture of Detox](how-detox-works.md#Architecture) will help with this section.
_Components running in the context of the test logic execution on the Node.js process on the host computer:_
1. **The Device Drivers layer:** The layer contains a collection of drivers, implementing - mostly, though not exclusively, the platform-specific details for the Detox [`device` object](https://github.com/wix/Detox/blob/master/docs/APIRef.DeviceObjectAPI.md) that is exposed in the Detox tests.
1. **The Device Drivers layer:** The layer contains a collection of drivers, implementing - mostly, though not exclusively, the platform-specific details for the Detox [`device` object](../api/device.md) that is exposed in the Detox tests.
The implementation is responsible for managing devices your tests will run on, in terms of device allocation, app installation user interactions (e.g. taps) execution and so on.
1. **Matchers:** code powering the `expect`, `element`, `waitFor` and `by` globals in your tests.
In essence, it translates and sends test-logic commands (such as taps and assertions) over the network to the device on which your tests are running. In turn, the device natively performs these commands.
@@ -103,12 +96,12 @@ class MyNewAllocationDriver {
constructor(deps) {
this.emitter = deps.eventEmitter;
}
async allocate(deviceConfig) {
// ...
return new Cookie(id); // This is where a cookie is formed once for the entire process
}
async free(cookie, options) {
// ...
}
@@ -130,7 +123,7 @@ class MyNewRuntimeDriver extends DeviceDriverBase {
constructor(deps, cookie) {
// ...
}
// ...
}
+90
View File
@@ -0,0 +1,90 @@
# Apps
The format of Detox config allows you to define inside it multiple app configs in a key-value manner, i.e.:
```js
{
"devices": {
// ... see above ...
},
"apps": {
"ios.debug": {
"type": "ios.app",
"binaryPath": "ios/build/Build/Products/Debug-iphonesimulator/example.app",
"build": "xcodebuild -project ios/example.xcodeproj -scheme example -configuration Debug -sdk iphonesimulator -derivedDataPath ios/build"
},
"android.release": {
"type": "android.apk",
"binaryPath": "path/to/myApp.apk",
"build": "..."
}
},
"configurations": {
// ... see above ...
}
}
```
An app config can have the following params:
| Configuration Params | Details |
| -------------------- |-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `type` | Mandatory property to discern app types: `ios.app`, `android.apk`. |
| `name` | Use only when working with multiple apps within the same configuration. See an example below. |
| `binaryPath` | Relative path to the ipa/app/apk due to be tested (make sure you build the app in a project relative path) |
| `build` | **\[optional]** Build command (normally an `xcodebuild` command you use to build your app), which can be called later using Detox CLI tool as a convenience. |
| `testBinaryPath` | (optional, Android only): relative path to the test app (apk) |
| `launchArgs` | **\[optional]** An object specifying arguments (key-values pairs) to pass through into the app, upon launching on the device. For more info, refer to the dedicated [launch-arguments guide](../Guide.LaunchArgs.md). |
To work with multiple apps within the same configuration you should be giving each app its name, e.g.:
```js
{
"apps": {
"driver.ios.release": {
"type": "ios.app",
"name": "driver",
"binaryPath": "path/to/driver.app"
},
"passenger.ios.release": {
"type": "ios.app",
"name": "passenger",
"binaryPath": "path/to/passenger.app"
}
},
"configurations": {
"ios.release": {
"device": "simulator",
"apps": ["driver", "passenger"]
}
}
}
```
After that, you can change the current app in your tests via [device API](api/device.md):
```js
await device.selectApp('driver');
await device.launchApp();
// ... run tests ...
await device.selectApp('passenger');
await device.launchApp();
// ... run tests ...
```
Similar to device configs, any app config can be inlined as well:
```js
{
"configurations": {
"ios.sim.debug": {
"device": "simulator",
"app": {
"type": "ios.app",
"binaryPath": "ios/build/Build/Products/Debug-iphonesimulator/example.app",
"build": "xcodebuild -project ios/example.xcodeproj -scheme example -configuration Debug -sdk iphonesimulator -derivedDataPath ios/build"
}
}
}
}
```
@@ -1,11 +1,76 @@
---
id: artifacts
slug: api/artifacts
title: Artifacts
sidebar_label: Artifacts
---
# Artifacts
## Artifacts
Detox can store artifacts such as transient screenshots and device logs.
You can control artifacts collection via Detox configuration:
```js
{
"artifacts": {
"rootDir": ".artifacts",
"pathBuilder": "./config/pathbuilder.js",
"plugins": {
"instruments": {"enabled": false},
"log": {"enabled": true},
"uiHierarchy": "enabled",
"screenshot": {
"shouldTakeAutomaticSnapshots": true,
"keepOnlyFailedTestsArtifacts": true,
"takeWhen": {
"testStart": false,
"testDone": true
}
},
"video": {
"android": {
"bitRate": 4000000
},
"simulator": {
"codec": "hevc"
}
}
}
},
"configurations": {
"ios.sim.release": {
// ...
"artifacts": {
"rootDir": ".artifacts/ios",
"plugins": {
"instruments": "all"
}
}
}
}
}
```
As can be seen from the example above, in a specific configuration you may override individual properties from the default artifacts
configuration. For instance, in the example above you can see that specifically in `ios.sim.release` we turn on `instruments` plugin.
CLI arguments (e.g., `--artifacts-location`, `--record-logs`) still have the highest priority and override their counterparts from JSON.
Also, that example demonstrates that you can use strings (identical to the ones from CLI) in parallel to the object configurations for plugins.
Below you can see mappings between the string presets and the corresponding objects:
| preset | object |
| ------- | ------------------------------------------------------------ |
| none | `{ "enabled": false }` |
| all | `{ "enabled": true }` |
| failing | `{ "enabled": true, "keepOnlyFailedTestsArtifacts": true }` |
| manual | `{ "enabled": true, "shouldTakeAutomaticSnapshots": false }` |
There is also a shortcut to disable artifacts for a specific configuration:
```js
{
"configurations": {
"ios.no-artifacts": {
// ...
"artifacts": false
}
}
}
```
Artifacts are various recordings during tests including, but not limited to, device logs, device screenshots and screen recordings (videos).
@@ -20,14 +85,14 @@ Artifacts are disabled by default. To enable them, specify via **launch argument
- To record `.dtxrec` (Detox Instruments recordings) for each test, add `--record-performance all`. To open those recordings, you’ll need [Detox Instruments](https://github.com/wix/DetoxInstruments). **NOTE:** only iOS is supported.
- To capture `.uihierarchy` snapshots (**iOS only, Xcode 12.0+**) on view action failures, add `--capture-view-hierarchy enabled`.
- To take `.png` screenshots before and after each test, add `--take-screenshots all` (or `--take-screenshots failing`, if you want to keep only screenshots of failing tests).\
Alternatively, you might leverage the [device.takeScreenshot()](APIRef.DeviceObjectAPI.md#devicetakescreenshotname) API for manual control.
Alternatively, you might leverage the [device.takeScreenshot()](api/device.md#devicetakescreenshotname) API for manual control.
##### Artifacts root directory
- To change artifacts root directory location (by default it is `./artifacts`), add `--artifacts-location <path>`.\
**NOTE:** There is a slightly obscure convention. If you want to create automatically a subdirectory with timestamp and configuration name (to avoid file overwrites upon consequent reruns), specify a path to directory that does not end with a slash. Otherwise, if you want to put artifacts straight to the specified directory (in a case where you make a single run only, e.g. on CI), add a slash (or a backslash) to the end.
```sh
```bash
detox test --artifacts-location /tmp/detox_artifacts # will also append /android.emu.release.2018-06-14 08:54:11Z
detox test --artifacts-location /tmp/detox_artifacts/ # won’t append anything, hereby treating it as a root
```
@@ -187,54 +252,25 @@ Hence, for example, if you wish to enable only `testDone` screenshots and leave
##### Video Plugin
To be done. See meanwhile the example in [artifacts configuration section](APIRef.Configuration.md#artifacts-configuration).
To be done. See meanwhile the example in [artifacts configuration section](#artifacts-configuration).
##### Log Plugin
To be done. See meanwhile the example in [artifacts configuration section](APIRef.Configuration.md#artifacts-configuration).
To be done. See meanwhile the example in [artifacts configuration section](#artifacts-configuration).
##### Instruments Plugin
To be done. See meanwhile the example in [artifacts configuration section](APIRef.Configuration.md#artifacts-configuration).
To be done. See meanwhile the example in [artifacts configuration section](#artifacts-configuration).
##### UI hierarchy Plugin
To be done. See meanwhile the example in [artifacts configuration section](APIRef.Configuration.md#artifacts-configuration).
##### Timeline Plugin
When enabled using the `--record-timeline all` argument to Detox, the time-line of the entire testing session is recorded, based on trace calls made by Detox internally, and explicit calls made in user test-code, combined.
The final outcome is a JSON-like file named `detox.trace.json`, which, if loaded into a Chrome-browser tab with the `chrome://tracing` URL, would look something like this:
![Timeline artifact example](img/timeline-artifact.png)
This _tracing_ view provides a visual, hierarchical representation of the various processes that took place during the execution of the testing session, over the execution’s _time-line_. These processes appear as hierarchical _sections_ -- sometimes visually ordered in a parent-child way, depending on their formation time and context.
To name a few predefined events, which are generated by Detox itself:
- **`detoxInit`:** Initialization of Detox, prior to running the suites associated with a specific tests file.
- **`awaitBoot`:** Waiting for an emulator to complete booting (thus being ready to run tests). Done in the surrounding context of `detoxInit` (and hence visually appears "below" it), as waiting for emulators' boot is an inherent part of Detox' initialization.
- **`appInstall`**, **`appUninstall`**.
- **"Sanity":** Execution of a user test suite called _Sanity_.
- **`reloadRN`:** A dynamic reload of the React-Native. Bound to calls to `device.reloadReactNative()`, specifically.
In the above example, the following can be observed:
1. There were 2 test workers (the Worker #⁠1, Worker #⁠2 time-lines) executing a total of two test suites.
1. There were 2 Android emulators used for running the test session, namely `emulator-17800` and `emulator-12466`. They were used by worker 1 and worker 2, respectively.
1. It took about a total of 54 seconds to initialize and run all the tests.
1. The first worker took longer to initialize (as depicted by the `detoxInit` section). In particular, that happened because it took longer for the associated emulator too finish bootstrapping (see the child `awaitBoot` section). That suggests there might be a problem with the test execution environment.
###### Purpose
**This artifact can be helpful in looking up ways to optimize the execution of your E2E tests.** It may surface shortcomings in the test environment’s ability to run the test, or provide a means to consider different ways of splitting up your tests over test files so as to better utilize parallelism.
The artifact can in fact be even better utilized -- to the level of inspecting the inside of your tests, by explicitly calling `trace` via the `detox.traceCall()` and `detox.trace.startSection()`, `detox.trace.endSection()` [APIs](APIRef.DetoxObjectAPI.md#detoxtracecall) inside your tests.
To be done. See meanwhile the example in [artifacts configuration section](#artifacts-configuration).
### Artifacts Structure
1. **Artifacts root folder** is created per detox test run. If, for instance,`--artifacts-location /tmp` is used with `--configuration ios.sim.release` configuration on 14th June 2018 at 11:02:11 GMT+02, then the folder `/tmp/ios.sim.release.2018-06-14 09:02:11Z` is created.
1. **Test folder** is created per test inside the root folder. The folder name consists of the test number, and the test’s full name provided to `detox.afterEach(testSummary)` as explained above and in [detox object](APIRef.DetoxObjectAPI.md) documentation. For instance, for the above example, the following folders will be created inside `/tmp/ios.sim.release.2018-06-14 09:02:11Z`:
1. **Test folder** is created per test inside the root folder. The folder name consists of the test number, and the test’s full name provided to `detox.afterEach(testSummary)` as explained above and in [detox object](../api/logger.mdx) documentation. For instance, for the above example, the following folders will be created inside `/tmp/ios.sim.release.2018-06-14 09:02:11Z`:
```plain text
✗ Assertions should assert an element has (accessibility)
@@ -260,35 +296,3 @@ artifacts/android.emu.release.2018-06-12 06:36:18Z/✗ Assertions should assert
artifacts/android.emu.release.2018-06-12 06:36:18Z/✗ Assertions should assert an element has (accessibility) id/test.mp4
artifacts/android.emu.release.2018-06-12 06:36:18Z/✗ Assertions should assert an element has (accessibility) id/afterEach.png
```
### Troubleshooting
#### Video Recording Issues on CI
For iOS, you might be getting errors on CI similar to this:
```plain text
Error: Error Domain=NSPOSIXErrorDomain Code=22 "Invalid argument" UserInfo={NSLocalizedDescription=Video recording requires hardware Metal capability.}.
```
Unfortunately, this error is beyond our reach. To fix it, you have to enable hardware acceleration on your build machine, or just disable video recording on CI if it is not possible to turn on the acceleration.
There might be a similar issue on Android when the screen recording process exits with an error on CI. While the solution might be identical to the one above, also you might try to experiment with other emulator devices and Android OS versions to see if it helps.
#### Detox Instruments is Installed in a Custom Location
If you have to use [Detox Instruments](https://github.com/wix/DetoxInstruments) installed in a custom location, you can point Detox to it with the `DETOX_INSTRUMENTS_PATH` environment variable, as shown below:
```bash
DETOX_INSTRUMENTS_PATH="/path/to/Detox Instruments.app" detox test ...
```
> **Note:** If **Detox Instruments** had been [integrated into your project](https://github.com/wix/DetoxInstruments/blob/master/Documentation/XcodeIntegrationGuide.md), then the integrated [Detox Profiler framework](https://github.com/wix/DetoxInstruments/tree/master/Profiler) will be used when profiling with Detox.
#### `Ctrl+C` Does Not Clean Up Temporary Files
This is a known issue. :man\_shrugging:
After you press `Ctrl+C` and stop the tests, some of temporary files won’t get erased (e.g. `/sdcard/83541_0.mp4` on Android emulator, or `/private/var/folders/lm/thz8hdxs4v3fppjh0fjc2twhfl_3x2/T/f12a4fcb-0d1f-4d98-866c-e7cea4942ade.png` on your Mac).
It cannot be solved on behalf of Detox itself, because the problem has to do with how Jest runner terminates its puppet processes.
The issue is on our radar, but the ETA for the fix stays unknown.
If you feel able to contribute the fix to [Jest](https://github.com/facebook/jest), you are very welcome.
+56
View File
@@ -0,0 +1,56 @@
# Behavior
If you need to tweak the flow of `detox.init()` or `detox.cleanup()` steps,
you have a few options to change. These are the default behavior values:
```json
{
"detox": {
"behavior": {
"init": {
"reinstallApp": true,
"exposeGlobals": true
},
"launchApp": "auto",
"cleanup": {
"shutdownDevice": false
}
}
}
}
```
The `launchApp: "auto"` setting can be changed to `"manual"` for cases when you want to [debug the
native codebase](../introduction/debugging.mdx) when running Detox tests. When set to `manual`, it also
changes the default value of `reinstallApp` to `false`.
Setting `reinstallApp: false` will make the tests reuse the currently installed app on the device,
provided you have installed it beforehand explicitly or manually.
If you do not wish to leak Detox globals (`expect`, `device`, `by`, etc.) to the global
scope, you can set `"exposeGlobals": false` and destructure them respectively from the
exported Detox interface:
```js
import { by, device, expect, element } from 'detox'; // TypeScript
const { by, device, expect, element } = require('detox'); // CommonJS
```
Also, you can override the behavior in specific Detox configurations:
```js
{
"behavior": {
// ... global behavior ...
},
"configurations": {
"ios.manual": {
"behavior": {
// ... overrides ...
"launchApp": "manual"
// ... overrides ...
}
}
}
}
```
+80
View File
@@ -0,0 +1,80 @@
# Devices
The format of Detox config allows you to define inside it multiple device configs in a key-value manner, i.e.:
```js
module.exports = {
"devices": {
"simulator": {
"type": "ios.simulator",
"device": {
// one of these or a combination of them
"id": "D53474CF-7DD1-4673-8517-E75DAD6C34D6",
"type": "iPhone 11 Pro",
"name": "MySim",
"os": "iOS 13.0"
}
},
"emulator": {
"type": "android.emulator",
"device": {
"avdName": "Pixel_2_API_29"
},
"utilBinaryPaths": [
"optional-property-with/path/to/test-butler-or-anything-else.apk"
]
},
"android.attached": {
"type": "android.attached",
"device": {
"adbName": "YOGAA1BBB412"
}
},
"android.genycloud": {
"type": "android.genycloud",
"device": {
"recipeUUID": "11111111-2222-3333-4444-555555555555"
// or recipeName: "MyRecipeName",
}
}
},
"apps": {
// ... see next API page ...
},
"configurations": {
// ... see previous API page ...
}
};
```
A device config can have the following params:
| Configuration Params | Details |
| -------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `type` | _**Required.** String Literal_. Mandatory property to discern device types: `ios.simulator`, `android.emulator`, `android.attached`, `android.genycloud` etc. |
| `device` | _**Required.** Object._ Device query, e.g. `{ "byType": "iPhone 11 Pro" }` for iOS simulator, `{ "avdName": "Pixel_2_API_29" }` for Android emulator or `{ "adbName": "<pattern>" }` for attached Android device with name matching the regex. |
| `bootArgs` | _Optional. String. Supported by `ios.simulator` and `android.emulator` only._ <br/> Supply an extra _String_ of arguments to `xcrun simctl boot ...` or `emulator -verbose ... @AVD_Name`. |
| `forceAdbInstall` | _Optional. Boolean. Supported for Android devices only._ <br/> A _Boolean_ value, `false` by default. When set to `true`, it tells `device.installApp()` to use `adb install`. Otherwise, it would use the combination of `adb push <app.apk>` and `adb shell pm install`. |
| `utilBinaryPaths` | _Optional. Array of strings. Supported for Android devices only._ <br/> An array of relative paths of _utility_ app (APK) binary-files to preinstall on the tested devices - once before the test execution begins.<br/>**Note**: these are not affected by various install-lifecycle events, such as launching an app with `device.launchApp({delete: true})`, which reinstalls the app. A good example of why this might come in handy is [Test Butler](https://github.com/linkedin/test-butler). |
| `gpuMode` | _Optional. String Literal (<code>auto \| host \| swiftshader\_indirect \| angle\_indirect \| guest</code>). Supported by `android.emulator` only._ <br/> A fixed **string** , which tells [in which GPU mode](https://developer.android.com/studio/run/emulator-acceleration#command-gpu) the emulator should be booted. |
| `headless` | _Optional. Boolean._ `false` by default. When set to `true`, it tells Detox to boot an Android emulator with `-no-window` option, or to not open the iOS Simulator app when running with Android or iOS respectively. |
| `readonly` | _Optional. Boolean. Supported by `android.emulator` only._ <br/> `false` by default. When set to `true`, it forces Detox to boot even a single emulator with `-read-only` option.<br/>**Note**: when used with multiple workers, this setting has no effect — emulators will be booted always with `-read-only`. |
Also, in the Detox `configurations` you can use the device configs as-is, without aliasing:
```js
{
"configurations": {
"ios.sim.debug": {
"device": {
"type": "ios.simulator",
"device": {
"type": "iPhone 12 Pro"
}
},
"app": "alias-to-app"
// ...
}
}
}
```
+11
View File
@@ -0,0 +1,11 @@
# Logger
## level
default level
## overrideConsole
## options
TODO: bunyan options
+150
View File
@@ -0,0 +1,150 @@
# Overview
## Config resolution
In order for Detox to know what device & app to use (and a lot more, actually), it needs some configuration to be statically available in a configuration file.
It supports both standalone configuration files, and a configuration bundling inside the project’s `package.json`.
In essence, Detox scans for the configuration to use, through multiple files.
It starts from the current working directory, and runs over the following options, in this order:
1. `.detoxrc.js`
1. `.detoxrc.json`
1. `.detoxrc`
1. `detox.config.js`
1. `detox.config.json`
1. `package.json`
So, you can have a Detox config in a standalone JS or JSON file:
```javascript
/* @type {Detox.DetoxConfig} */
module.exports = {
devices: { /* ... */ },
apps: { /* ... */ },
configurations: { /* ... */ },
};
```
or as a named section inside your `package.json`:
```json
{
"name": "your-project",
"version": "X.Y.Z",
"scripts": {},
// highlight-start
"detox": {
"devices": {},
"apps": {},
"configurations": {},
}
// highlight-end
}
```
If you prefer to read TypeScript files instead of docs, you can open now
[the typings file](https://github.com/wix/Detox/blob/master/detox/index.d.ts) provided by Detox.
## Extending configs
Detox config files can be extensible and be extended if you ever need to share certain settings across multiple mobile projects, e.g.:
```json
{
// highlight-next-line
"extends": "@my-org/detox-preset",
"apps": {
// …
},
}
```
Please note that `extends` has to be a valid Node module path. Relative module paths will be resolved relatively
to the Detox config file which contains that specific `extends` property, e.g.:
```js
// given: ~/Projects/my-project/.detoxrc.json
{ extends: "./e2e/detox-base-config" }
// goes to: ~/Projects/my-project/e2e/detox-base-config.js
{ extends: "./configs/base" }
// then goes to: ~/Projects/my-project/e2e/configs/base/index.js
// and so on...
```
## Individual configurations
`configurations` holds all the device/app-oriented configurations. To select a specific configuration when running Detox in command-line (i.e. `detox build`, `detox test`), use the `--configuration` argument.
Note: If there is only one configuration in `configurations`, Detox will default to it.
| Configuration Params | Details |
| -------------------- | -------------------------------------------------------------------------------------------------------------------- |
| `device` | Device config (object) or an alias pointing to an already defined device in `"devices"` dictionary (see below). |
| `app` | App config (object) or an alias pointing to an already defined application in `"apps"` dictionary (see below). |
| `apps` | Same as the `app`, but that is an array form used for multi-app testing. Mutually exclusive with the `app` property. |
| `artifacts` | Overrides to the artifacts config. See [Artifacts config](artifacts.md). |
| `behavior` | Overrides to the behavior config. See [Behavior config](behavior.md). |
| `session` | Overrides to the session config. See [Session config](session.md). |
| | |
| `runnerConfig` | Path to the test runner config. Default value: `e2e/config.json`. |
| `specs` | A default glob pattern for a test runner to use when no test files are specified, e.g.: `e2e/**/*.test.js` |
**Example:**
```js
{
// ...
"detox": {
// ...
"devices": {
// ... see in the next sections ...
},
"apps": {
// ... see in the next sections ...
},
"session": {
// ... see in the next sections ...
},
"configurations": {
"ios.sim.debug": {
"device": "simulator",
"app": "ios.debug"
},
"android.emu.release": {
"device": "emulator",
"app": "android.release"
},
"android.att.release": {
"device": "android.attached",
"app": "android.release"
},
"android.genymotion.release": {
"device": "android.genycloud",
"app": "android.release"
}
}
}
}
```
If you have multiple configurations, you'll have to append `-c <configurationName>` to every invocation of
`detox build` and `detox test` CLI, e.g.:
```bash
detox build -c ios.sim.debug
detox test -c ios.sim.debug
```
If this is inconvenient, and you can have some configuration as a default choice, there's a property for that:
```diff
+"selectedConfiguration": "ios.sim.debug",
"configurations": {
"ios.sim.debug": {
"device": "simulator",
"app": "ios.debug"
},
```
Obviously, if you have only one configuration, there's no need to specify its name, just use `detox build` and
`detox test` as-is.
+58
View File
@@ -0,0 +1,58 @@
# Session
Detox can either initialize a server using a generated configuration, or can be overridden with a manual configuration:
```json
{
"session": {
"server": "ws://localhost:8099",
"sessionId": "YourProjectSessionId"
}
}
```
When you define a session config, the Detox server won’t start automatically anymore — it is assumed that
you will be running it independently via `detox run-server` CLI command. Alternatively, you can set the
`autoStart` property to be explicitly `true`:
```diff
"session": {
+ "autoStart": true,
"server": "ws://localhost:8099",
"sessionId": "YourProjectSessionId"
```
Defining an explicit session config with `server` and `sessionId` also means you cannot use multiple workers,
since the specified port will become busy for any test worker next to the first one to occupy it.
Session can be set also per device configuration — then it takes a higher priority over the global
session config:
```json
{
"configurations": {
"ios.sim.debug": {
// ...
"session": {
"server": "ws://localhost:8099",
"sessionId": "YourProjectSessionId"
}
}
}
}
```
Also, you can specify an optional numeric `debugSynchronization` parameter
(see also `--debug-synchronization` in [`detox-cli` test section](../api/detox-cli.md#test)).
When an action/expectation takes a significant amount time, use this option to print device synchronization status.
The status will be printed if the action takes more than _\[N]_ ms to complete.
```json
{
"session": {
"debugSynchronization": 20000
}
}
```
To disable `debugSynchronization` explicitly, use `0`.
+100
View File
@@ -0,0 +1,100 @@
# Test runner
| Property | Value | Description |
| ------------ | -------- | --------------------------------------------------------------------------- |
| `testRunner` | `"jest"` | _Required._ Should be `"jest"` for the proper `detox test` CLI functioning. |
A typical Detox configuration in `.detoxrc.js` file looks like:
```json
{
"runnerConfig": "e2e/config.json",
"devices": {
"simulator": {
"type": "ios.simulator",
"device": {
"type": "iPhone 12 Pro Max"
}
}
},
"apps": {
"ios.release": {
"type": "ios.app",
"binaryPath": "ios/build/Build/Products/Release-iphonesimulator/example.app",
"build": "<...xcodebuild command...>",
}
},
"configurations": {
"ios.sim.release": {
"device": "simulator",
"app": "ios.release"
}
}
}
```
## Jest config
| Property | Value | Description |
| ----------------- | --------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `maxWorkers` | `1` | _Recommended._ It prevents potential overallocation of mobile devices according to the default logic of Jest (`maxWorkers = cpusCount — 1`) for the default workers count. To override it, [use CLI arguments](../api/detox-cli.md#test), or see [Jest documentation](https://jestjs.io/docs/configuration#maxworkers-number--string) if you plan to change the default value in the config. |
| `testEnvironment` | `"./environment"` | _Required._ Needed for the proper functioning of Jest and Detox. See [Jest documentation](https://jestjs.io/docs/en/configuration#testenvironment-string) for more details. |
| `testRunner` | `"jest-circus/runner"` | _Required._ Needed for the proper functioning of Jest and Detox. See [Jest documentation](https://jestjs.io/docs/en/configuration#testrunner-string) for more details. |
| `testTimeout` | `120000` | _Required_. Overrides the default timeout (5 seconds), which is usually too short to complete a single end-to-end test. |
| `reporters` | `["detox/runners/jest/reporter"]` | _Recommended._ Sets up our streamline replacement for [Jest’s default reporter](https://jestjs.io/docs/en/configuration#reporters-array-modulename-modulename-options), which removes Jest’s default buffering of `console.log()` output. That is helpful for end-to-end tests since log messages appear on the screen without any artificial delays. |
| `verbose` | `true` | _Conditional._ Must be `true` if above you have replaced Jest’s default reporter with Detox’s `reporter`. Optional otherwise. |
A typical `jest-circus` configuration in `e2e/config.json` file would look like:
```json
{
"testRunner": "jest-circus/runner",
"testEnvironment": "./environment",
"testTimeout": 120000,
"reporters": ["detox/runners/jest/reporter"],
"verbose": true
}
```
**Notes:**
- The custom `SpecReporter` is recommended to be registered as a listener. It takes care of logging on a per-spec basis (i.e. when `it('...')` functions start and end) — which Jest does not do by default.
- The custom `WorkerAssignReporter` prints for every next test suite which device is assigned to its execution.
This is how a typical Jest log output looks when `SpecReporter` and `WorkerAssignReporter` are enabled in `streamline-reporter` is set up in `config.json` and
`SpecReporter` added in `e2e/environment.js`:
![Streamlined output](../img/jest-guide/streamlined_logging.png)
### Writing Tests
There are some things you should notice:
- Don’t worry about mocks being used, Detox works on the compiled version of your app.
- Detox exposes its primitives (`expect`, `device`, ...) globally, it will override Jest’s global `expect` object.
- use `import jestExpect from 'expect'` if you need.
### Parallel Test Execution
Through Detox' CLI, Jest can be started with [multiple workers](../Guide.ParallelTestExecution.md) that run tests simultaneously, e.g.:
```bash
detox test --configuration <yourConfigurationName> --maxWorkers 2
```
In this mode, Jest effectively assigns one worker per each test file.
Per-spec logging offered by the `SpecReporter` mentioned earlier, does not necessarily make sense, as the workers' outputs get mixed up.
By default, we disable `SpecReporter` in a multi-workers environment.
If you wish to force-enable it nonetheless, the [`--jest-report-specs`](../api/detox-cli.md#test) CLI option can be used with `detox test`, e.g.:
```bash
detox test --configuration <yourConfigurationName> --maxWorkers 2 --jest-report-specs
```
### How to Run Unit and E2E Tests in the Same Project
- Create different Jest configs for unit and E2E tests, e.g. in `e2e/config.json` (for Detox) and `jest.config.js`
(for unit tests). For example, in Jest’s E2E config you can set `testMatch` to look for `<rootDir>/e2e/**/*.test.js$`
glob, and this way avoid accidental triggering of unit tests in your `src/` or `lib/` folder.
- To run your E2E tests, use `detox test` command (or `npx detox test`, if you haven’t installed `detox-cli`).
+20
View File
@@ -0,0 +1,20 @@
# Using Genymotion Cloud
As the number of your end-to-end tests grows, the overall test session duration might easily surpass an hour or two.
A good idea first would be to parallelize the test execution using your test runner (e.g. for Jest that
would be forwarding `--maxWorkers <N>`), but this approach has its limitations. An average build agent could manage
running a few virtual devices at once, but running a dozen devices at once would make it slow and unreliable.
So, if you're running into scaling issues, it's the right time to move on to SaaS platforms, where you can
start and stop devices on demand at any scale. At the moment, Detox can offer you a first-class integration with
[Genymotion Cloud], the platform that offers cloud-based Android Virtual Devices.
## Prerequisites
* Android SDK platform tools with `adb` installed
* `gmsaas` [installed and configured](https://docs.genymotion.com/gmsaas/01_Get_Started)
TODO
[Genymotion Cloud]: https://cloud.geny.io/
@@ -1,11 +1,4 @@
---
id: screenshots
slug: api/screenshots
title: Taking Screenshots
sidebar_label: Taking Screenshots
---
## Taking Screenshots
# Taking Screenshots
Detox supports taking in-test screenshots of the device, making the result immediately available in the form of an image file.
@@ -28,8 +21,8 @@ describe('Members area', () => {
it('should greet the member with an announcement', async () => {
const imagePath = (take screenshot from the device); // Discussed below
expectBitmapsToBeEqual(imagePath, snapshottedImagePath);
});
expectBitmapsToBeEqual(imagePath, snapshottedImagePath);
});
});
function expectBitmapsToBeEqual(imagePath, expectedImagePath) {
@@ -51,7 +44,7 @@ Taking a screenshot of the entire screen can be done using a device-level API:
const imagePath = await device.takeScreenshot('opened general section');
```
The API immediately returns the path of a temporary, readable image file where the screenshot is stored, all-the-while scheduling the transferring of it to the [artifacts folder](APIRef.Artifacts.md#enabling-artifacts) upon completion of the currently running test.
The API immediately returns the path of a temporary, readable image file where the screenshot is stored, all-the-while scheduling the transferring of it to the [artifacts folder](../config/artifacts.md#enabling-artifacts) upon completion of the currently running test.
**Returns:**
@@ -76,7 +69,7 @@ Means of creation of the final image as an artifact is tightly connected to the
This API well-captures all elements, although alongside surrounding "visual noise" such as the navigation bar, as can be seen in the image below:
![device-screenshot](img/device-screenshot.png)
![device-screenshot](../img/device-screenshot.png)
As the image includes, for example, the current time (in the top-left corner), running the test in any _different_ time would unnecessarily result in an utter comparison failure, making the test downright useless. Fortunately, this can be resolved, by putting the device into "demo mode" (i.e. freezing the irrelevant, volatile elements) . For example (credits - [Miki](https://github.com/M-i-k-e-l)):
@@ -117,7 +110,7 @@ const imagePath = await element(by.id('announcementsRoot')).takeScreenshot('welc
In this example, the image-file specified by `imagePath` will hold the visual content of a native view whose test ID is `announcementsRoot`, alongside all of the views in the view-hierarchy formed by it as the root-view. Visually, this can be, for example:
![Announcements view](img/element-screenshot-view.png)
![Announcements view](../img/element-screenshot-view.png)
Meaning, assuming `announcementsRoot` has been specified over some ancestor view which has both the `Announcement` title _and_ the card as its direct or indirect children, the result would include both. That, in turns, also includes the card’s children, such as the avatar, welcome text, etc.
@@ -127,11 +120,11 @@ Focusing on specific elements, this approach is key to more stable comparisons,
Consider this situation in one of the app’s screens, where the upcoming schedule overlaps the top-hand announcement card:
![overlap](img/element-screenshot-overlap.png)
![overlap](../img/element-screenshot-overlap.png)
Taking an element-screenshot of the announcement part alone, would yield a proper result, leaving this bug overlooked:
![announcement element](img/element-screenshot-view.png)
![announcement element](../img/element-screenshot-view.png)
Only by taking the element-screenshot of a common ancestor, will this bug be surfaced. However, in turn, that can affect stability, as the result is now sensitive to more details such as padding and background color.
Binary file not shown.

After

Width:  |  Height:  |  Size: 161 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 204 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 153 KiB

+319
View File
@@ -0,0 +1,319 @@
---
id: building-with-detox
slug: introduction/building-with-detox
---
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import PrepareAppConfigsIos from './partials/_building-with-detox-apps-ios.mdx';
import PrepareAppConfigsAndroid from './partials/_building-with-detox-apps-android.mdx';
import PrepareDeviceConfigsIos from './partials/_building-with-detox-devices-ios.mdx';
import PrepareDeviceConfigsAndroid from './partials/_building-with-detox-devices-android.mdx';
import DetoxBuild from './partials/_building-with-detox-build.mdx';
# Building with Detox
:::info
This article mainly covers standard React Native projects.
If some steps don't look applicable to your project, please adapt them accordingly, relying on the common sense –
look for other file locations, use custom build commands and so on.
:::
After Detox generated these files in your project's root, you still have some work to do with them:
* `.detoxrc.js` – Detox config file;
* `e2e/jest.config.js` – Jest configuration;
* `e2e/starter.test.js` – dummy first test.
## Step 1: App configs
In this step you need to provide Detox with the right **commands to build** your app for iOS and Android,
and also the right **paths to the app binaries** so that Detox can install your app on the device before
actually starting the tests.
<Tabs groupId="mobileOs">
<TabItem value="iOS" label="iOS" default>
<PrepareAppConfigsIos />
</TabItem>
<TabItem value="Android" label="Android">
<PrepareAppConfigsAndroid />
</TabItem>
</Tabs>
## Step 2: Device configs
By default, Detox config suggests default device types for iOS and Android:
```javascript title=".detoxrc.js"
/** @type {Detox.DetoxConfig} */
module.exports = {
// ...
devices: {
simulator: {
type: 'ios.simulator',
device: {
// highlight-next-line
type: 'iPhone 12',
},
},
attached: {
type: 'android.attached',
device: {
// highlight-next-line
adbName: '.*', // any attached device
},
},
emulator: {
type: 'android.emulator',
device: {
// highlight-next-line
avdName: 'Pixel_3a_API_30_x86',
},
},
},
};
```
Here's how you can check they are correct and change them if you need something else:
<Tabs groupId="mobileOs">
<TabItem value="iOS" label="iOS">
<PrepareDeviceConfigsIos />
</TabItem>
<TabItem value="Android" label="Android" default>
<PrepareDeviceConfigsAndroid />
</TabItem>
</Tabs>
## Step 3: Android configuration
:::tip
If you want to try out your tests right away on iOS,
you can skip to [Step 4: Build Your App](#step-4-build-your-app)
and revisit it when you're ready to move forward with Android.
:::
Assuming you have a regular React Native project, these are the files you normally would need to
patch or create if they are missing:
* **Build scripts:**
* `android/build.gradle`
* `android/app/build.gradle`
* **Native test code:**
* `android/app/src/androidTest/java/com/<your.package>/DetoxTest.java`
* **Manifests:**
* `android/app/src/main/AndroidManifest.xml`
* `android/app/src/main/res/xml/network_security_config.xml`
### 3.1. Patching build scripts
Open your main build script and apply the suggested changes:
```diff title="android/build.gradle"
buildscript {
ext {
buildToolsVersion = "31.0.0"
// highlight-next-line
minSdkVersion = 21 // (1)
compileSdkVersion = 30
targetSdkVersion = 30
// highlight-next-line
+ kotlinVersion = 'X.Y.Z' // (2)
}
…
dependencies {
classpath("com.android.tools.build:gradle:7.1.1")
classpath("com.facebook.react:react-native-gradle-plugin")
classpath("de.undercouch:gradle-download-task:5.0.1")
// highlight-next-line
+ classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion") // (3)
…
allprojects {
repositories {
…
google()
// highlight-start
+ maven { // (4)
+ url("$rootDir/../node_modules/detox/Detox-android")
+ }
// highlight-end
maven { url 'https://www.jitpack.io' }
}
```
Here is the explanation of those changes, numbered 1-4:
1. Make sure your `minSdkVersion` is at least 18 or higher.
1. We recommend you to define a global `kotlinVersion` constant you would use in the next step.
Replace `X.Y.Z` with the actual version number.
To get one, open **Android Studio**, go to `Preferences > Languages & Frameworks > Kotlin` and
look at `Current Kotlin plugin version` field. For example, `211-1.5.30-release-408-AS7442.40`
means you have version `1.5.30`.
![](../img/android/get-kotlin-version.png)
1. The line adds [Kotlin Gradle plugin](https://mvnrepository.com/artifact/org.jetbrains.kotlin/kotlin-gradle-plugin)
to the build script. If your project is not entirely new, there's a chance you might have it already, so make sure
you aren't adding it twice. :wink:
1. Last, we are adding Detox as a precompiled native dependency, `.aar`. If you need to have Detox as a
_compiling dependency_ instead, consult the respective section in [Debugging](debugging.mdx#native-application-code) guide.
Now let's move on to the next build script and prepare it:
```diff title="android/app/build.gradle"
…
android {
…
defaultConfig {
…
versionCode 1
versionName "1.0"
+ testBuildType System.getProperty('testBuildType', 'debug')
+ testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
…
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ proguardFile "${project(':detox').projectDir}/proguard-rules-app.pro"
signingConfig signingConfigs.release
}
}
…
dependencies {
+ androidTestImplementation('com.wix:detox:+')
+ implementation 'androidx.appcompat:appcompat:1.1.0'
implementation fileTree(dir: "libs", include: ["*.jar"])
```
:::info ProGuard notice
Detox relies on
[Android Reflection API](https://developer.android.com/reference/java/lang/reflect/package-summary)
to integrate with React Native on Android, that's why you have to exempt some of its native code from
[ProGuard minification](https://developer.android.com/studio/build/shrink-code).
Otherwise, you'll be seeing Detox crashing or hanging up infinitely upon an attempt to
run tests with your app built in **release mode**.
:::
### 3.2. Adding an auxiliary Android test
Detox requires from your project to have a single dummy native Android test with some special content,
which will be picked up by `testRunner` that you just added in the previous step, so let's create it now.
Copy the snippet below to create a file under the following path (where `<your.package>` is your actual
package name):
```typescript title="android/app/src/androidTest/java/com/<your.package>/DetoxTest.java" showLineNumbers
// highlight-next-line
package com.<your.package>; // (1)
import com.wix.detox.Detox;
import com.wix.detox.config.DetoxConfig;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.LargeTest;
import androidx.test.rule.ActivityTestRule;
@RunWith(AndroidJUnit4.class)
@LargeTest
public class DetoxTest {
@Rule // (2)
// highlight-next-line
public ActivityTestRule<MainActivity> mActivityRule = new ActivityTestRule<>(MainActivity.class, false, false);
@Test
public void runDetoxTests() {
DetoxConfig detoxConfig = new DetoxConfig();
detoxConfig.idlePolicyConfig.masterTimeoutSec = 90;
detoxConfig.idlePolicyConfig.idleResourceTimeoutSec = 60;
detoxConfig.rnContextLoadTimeoutSec = (BuildConfig.DEBUG ? 180 : 60);
Detox.runTests(mActivityRule, detoxConfig);
}
}
```
You can see there are two lines (1 and 18) that require extra care:
1. Replace with your package name. To look it up, you could copy and paste the first line from `android/app/src/main/java/com/<your.package>/MainActivity.java`.
1. Usually not the case, but you might have a custom activity name instead of a default `MainActivity`. To check whether it is so or not, open your `android/app/src/main/AndroidManifest.xml`,
and look up how your main activity is called:
```plain text
…
<activity
// highlight-next-line
android:name=".MainActivity"
android:label="@string/app_name"
android:launchMode="standard"
```
### 3.3. Enabling unencrypted traffic for Detox
:::info
For Detox to work, its native code running on Android device has to be able to connect to the Node.js host running tests.
It sends an unencrypted HTTP traffic via virtual `localhost` interface, that's why you need to create a new file which
adds a couple of exceptions to the security rules.
If properly configured, this approach in no way compromises the security settings of your app.
For more details, refer to [Android’s security-config guide](https://developer.android.com/training/articles/security-config)
and the [dedicated article](https://android-developers.googleblog.com/2016/04/protecting-against-unintentional.html)
in the Android developers blog.
:::
Create a new network security config file for Android (or patch it if you have one):
```xml title="android/app/src/main/res/xml/network_security_config.xml"
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<domain-config cleartextTrafficPermitted="true">
<domain includeSubdomains="true">10.0.2.2</domain>
<domain includeSubdomains="true">localhost</domain>
</domain-config>
</network-security-config>
```
If you had no network security config before, it means you also have to register it after creation:
```diff title="android/app/src/main/AndroidManifest.xml"
<manifest>
<application
…
+ android:networkSecurityConfig="@xml/network_security_config">
</application>
</manifest>
```
:trophy: Pat yourself on the back! The hardest part is over, now your Android app is ready to be used with Detox.
## Step 4: Build and run tests
<Tabs groupId="configurationName">
<TabItem value="ios.sim.debug" label="iOS (Debug)">
<DetoxBuild configurationName={'ios.sim.debug'} debug />
</TabItem>
<TabItem value="ios.sim.release" label="iOS (Release)">
<DetoxBuild configurationName={'ios.sim.release'} />
</TabItem>
<TabItem value="android.emu.debug" label="Android (Debug)">
<DetoxBuild configurationName={'android.emu.debug'} debug/>
</TabItem>
<TabItem value="android.emu.release" label="Android (Release)">
<DetoxBuild configurationName={'android.emu.release'} />
</TabItem>
</Tabs>
+168
View File
@@ -0,0 +1,168 @@
import CodeBlock from '@theme/CodeBlock';
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import CompilingIOS from './partials/_debugging-native-code-compliing-ios.mdx';
import CompilingAndroid from './partials/_debugging-native-code-compliing-android.mdx';
import ConfigIOS from './partials/_debugging-native-code-config-ios.mdx';
import ConfigAndroid from './partials/_debugging-native-code-config-android.mdx';
import RunIos from './partials/_debugging-native-code-run-ios.mdx';
import RunAndroid from './partials/_debugging-native-code-run-android.mdx';
# Debugging
## Detox Tests
If you need to walk through your Detox tests step by step, add a `debugger` statement
inside your test to mark a starting point, e.g.:
```diff title="e2e/starter.test.js"
describe('Example', () => {
beforeAll(async () => {
await device.launchApp();
+ debugger;
});
```
Now run Detox with that specific test and `--inspect-brk` flag, e.g.:
```bash
detox test --inspect-brk -c android.emu.debug e2e/starter.test.js
```
Assuming you're using Jest, you'll see something like:
```bash
DETOX_CONFIGURATION="android.emu.debug" node --inspect-brk ./node_modules/.bin/jest --config e2e/jest.config.js --runInBand e2e/starter.test.js
Debugger listening on ws://127.0.0.1:9229/3dedd03b-8896-4ab8-a0a8-1b647abb9c98
For help, see: https://nodejs.org/en/docs/inspector
```
:::info
To learn more about debugging with `--inspect-brk`, refer to
[Debugging — Getting Started](https://nodejs.org/en/docs/guides/debugging-getting-started/)
on the official Node.js website. This tutorial suggests using Google Chrome for debugging,
but you can also use an IDE to connect to the debugger.
:::
Open `Google Chrome` and go to `chrome://inspect` tab, where you'll see `./node_modules/.bin/jest` as a remote
target waiting until you click `inspect` to attach to it.
![](../img/inspect-brk.png)
Happy debugging!
## JavaScript application code
Use debug configurations of your app that rely on React Native Packager running on port 8081 (or another):
* `ios.sim.debug`
* `android.emu.debug`
For the rest of details, please refer to [React Native – Debugging](https://reactnative.dev/docs/debugging).
## Native application code
:::info Note
This workflow is mostly useful for investigating weird crashes or when contributing to Detox itself.
:::
### Setting Detox up as a compiling dependency
<Tabs groupId="mobileOs">
<TabItem value="iOS" label="iOS" default>
<CompilingIOS />
</TabItem>
<TabItem value="Android" label="Android">
<CompilingAndroid />
</TabItem>
</Tabs>
### Add a "manual" configuration to your Detox config
<Tabs groupId="mobileOs">
<TabItem value="iOS" label="iOS" default>
<ConfigIOS />
</TabItem>
<TabItem value="Android" label="Android">
<ConfigAndroid />
</TabItem>
</Tabs>
While the `behavior` section is a **mandatory** thing to include, there are a few more optional
parameters to disable various side effects and make life easier when debugging:
```diff
"behavior": {
"launchApp": "manual"
},
+ "session": {
+ "autoStart": true,
+ "debugSynchronization": 0,
+ "server": "ws://localhost:8099",
+ "sessionId": "test"
+ },
+ "testRunner": {
+ "args": {
+ "testTimeout": 999999
+ }
+ }
+ "artifacts": false
```
- Using a preconfigured `session` with an autostarting server removes the legwork of copying and
pasting values to the instrumentation runner launch arguments dialog every time before any launch
from the IDE. Otherwise, by default when the `session` object omitted, `server` and `sessionId`
are randomly generated for every new test session.
- The `debugSynchronization: 0` override matters only if you have a global `session` config
with `debugSynchronization` set to a positive integer value. Otherwise, it is not needed. The point
is to disable regular app polling requests during debugging, since that only can hinder the debugging.
- If you are using Jest as a test runner, you might want to prolong the test timeout via forwarding
`--testTimeout 999999` to it.
- Setting `artifacts: false` override also matters only if you have a global `artifacts` config.
The motivation is to disable irrelevant taxing activities on the device such as capturing logs
screenshots, videos and so on. If your investigation addresses a specific artifact plugin glitch
on the native side, then just disable all the non-relevant plugins. See
[Configuration > Artifacts](../config/artifacts.md) document for the reference.
### Run a specific test
Usually, you would want to focus on a specific test suite to save time, e.g.:
<Tabs groupId="mobileOs">
<TabItem value="iOS" label="iOS">
<CodeBlock language="sh">
detox test -c ios.manual e2e/someSuite.test.js
</CodeBlock>
</TabItem>
<TabItem value="Android" label="Android">
<CodeBlock language="sh">
detox test -c android.manual e2e/someSuite.test.js
</CodeBlock>
</TabItem>
</Tabs>
:::caution
Don't use multiple workers (`-w, --maxWorkers`) if you set `session.sessionId` to a constant value.
:::
Afterwards, you should see your test suite starting as usual until it reaches the app launch, where
Detox stops instead and prompts you to launch the app from the IDE:
<Tabs groupId="mobileOs">
<TabItem value="iOS" label="iOS">
<RunIos />
</TabItem>
<TabItem value="Android" label="Android">
<RunAndroid />
</TabItem>
</Tabs>
+134
View File
@@ -0,0 +1,134 @@
import CodeBlock from '@theme/CodeBlock';
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import IntroExpo from './partials/_getting-started-expo.md';
import IntroOther from './partials/_getting-started-other.mdx';
# Getting Started
**Welcome to Detox!**
In this guide, we will walk you through setting Detox up in your project, one step at a time.
You will find that some steps are longer than the others: some are just one-paragraph long, while for others we have a dedicated multistep guide worked out. Bear with us - it is all necessary, and once set-up, it is easy to move forward with writing tests very rapidly.
Please select type of your mobile application before you start the tutorial:
<Tabs groupId="appType">
<TabItem value="start-rn" label="React Native" default />
<TabItem value="start-expo" label="Expo">
<IntroExpo />
</TabItem>
<TabItem value="start-other" label="Other">
<IntroOther />
</TabItem>
</Tabs>
## Setting up the environment
Your first step would be to complete the
[📚 React Native Environment Setup Guide](https://reactnative.dev/docs/next/environment-setup).
![](../img/rn-env.png)
<p>
Open the link above and switch there to <b>React Native CLI Quickstart</b> tab to see
the interactive tutorial for <b>Development OS</b> and <b>Target OS</b> of your choice.
</p>
<p>
Follow all
the steps <span style={{color: 'red'}}>(yes, even if you have a native app!)</span> and
make sure you can create and run React Native apps on virtual testing devices.
</p>
![](../img/rn-env-done.png)
## Installing Detox prerequisites
To complete the environment setup, you still have 2 steps ahead: installing `detox-cli` and `applesimutils`.
### 1. Command Line Tools (`detox-cli`)
`detox-cli` is merely a script that passes commands through to
a local Detox executable located at `node_modules/.bin/detox`,
making it easier to operate Detox from the command line, e.g. `detox test -c ios.sim.debug`.
It should be installed globally, enabling usage of the command line tools outside your npm scripts:
```bash npm2yarn
npm install detox-cli --global
```
On the other hand, if you are fine with running Detox commands with `npx detox ...`, you may skip installing `detox-cli`.
### 2. [MacOS Only] `applesimutils`
This tool is **required** by Detox to work with iOS simulators. The recommended way to install
[`applesimutils`](https://github.com/wix/AppleSimulatorUtils) is via [Homebrew](https://brew.sh):
```bash
brew tap wix/brew
brew install applesimutils
```
:::info Note
Make sure to periodically update your version of `applesimutils` to the latest version.
:::
## Setting up the project
<Tabs groupId="appType">
<TabItem value="start-rn" label="React Native" default>
Go to your project's root folder (where <code>package.json</code> is found) and run:
</TabItem>
<TabItem value="start-other" label="Native iOS">
<p>Create a <code>package.json</code> in your project's root by running this command:</p>
<CodeBlock language="bash">
npm init -y
</CodeBlock>
<p>And remember to add the <code>node_modules</code> folder to your <code>.gitignore</code> file.</p>
<p>Now you are ready to install the Detox itself. Run:</p>
</TabItem>
</Tabs>
```bash npm2yarn
npm install detox --save-dev
```
The next step would be to **install a test runner**. Out of the box, Detox offers you first-class integration
with [Jest](https://jestjs.io), and that is our official recommendation:
```bash npm2yarn
npm install "jest@>=27.2.5" --save-dev
```
:::info
The command above will install the **latest Jest version** regardless of the constraint, but `@>=27.2.5` is
recommended in the first place to prevent you from getting an incompatible Jest version unknowingly, under influence
of the existing lock files. Reportedly, `package-lock.json` could restrict `npm install jest` to installing
an older, unsupported version `26.x`.
:::
Now, when all the dependencies are installed, initialize Detox in your project:
```bash
detox init
```
Normally you should see an output like:
```plain text
Created a file at path: .detoxrc.js
Created a file at path: e2e/jest.config.js
Created a file at path: e2e/starter.test.js
```
:::tip
If you see a message like `command not found: detox`, make sure you have [installed Detox command line tools](#1-command-line-tools-detox-cli).
:::
Now, when your environment and a boilerplate with configuration are ready, let's move to the next section,
[Building for Detox](building-with-detox.mdx).
@@ -0,0 +1,49 @@
<!-- markdownlint-configure-file { "no-trailing-punctuation": 0 } -->
import FlavorizedCodeBlock from '@site/src/components/FlavorizedCodeBlock';
Check **binaryPath** and **build** configs for `android.debug` and `android.release` mode in your Detox config:
```javascript title=".detoxrc.js"
module.exports = {
apps: {
'android.debug': {
type: 'android.apk',
// highlight-start
binaryPath: 'android/app/build/outputs/apk/debug/app-debug.apk',
build: 'cd android && ./gradlew assembleDebug assembleAndroidTest -DtestBuildType=debug'
// highlight-end
},
'android.release': {
type: 'android.apk',
// highlight-start
binaryPath: 'android/app/build/outputs/apk/release/app-release.apk',
build: 'cd android && ./gradlew assembleRelease assembleAndroidTest -DtestBuildType=release'
// highlight-end
},
// ...
},
// ...
};
```
If you have a typical React Native project, these values should already be correct.
On the other hand, if your app has extra [`productFlavors`](https://developer.android.com/studio/build/build-variants#product-flavors)
(let's imagine you have `driver` and `passenger` flavors of a taxi application), then you should rewrite your apps config
for both **debug** and **release** configurations, e.g.:
<FlavorizedCodeBlock
language="diff"
header={' apps: {\n'}
flavors={['Driver', 'Passenger']}
>
{(conf) => `\
'${conf.toLowerCase()}.android.debug': {
type: 'android.apk',
- binaryPath: 'android/app/build/outputs/apk/debug/app-debug.apk',
+ binaryPath: 'android/app/build/outputs/apk/${conf.toLowerCase()}/debug/app-${conf.toLowerCase()}-debug.apk',
- build: 'cd android && ./gradlew assembleDebug assembleAndroidTest -DtestBuildType=debug',
+ build: 'cd android && ./gradlew assemble${conf}Debug assemble${conf}DebugAndroidTest -DtestBuildType=debug',
},`}
</FlavorizedCodeBlock>
@@ -0,0 +1,48 @@
<!-- markdownlint-configure-file { "no-trailing-punctuation": 0 } -->
import FlavorizedCodeBlock from '@site/src/components/FlavorizedCodeBlock';
Open your Detox config and replace `YOUR_APP` placeholder with the actual app name, e.g.:
<FlavorizedCodeBlock
language="diff"
title={'.detoxrc.js'}
header={' apps: {\n'}
flavors={['Debug', 'Release']}
>
{(conf) => `\
'ios.${conf.toLowerCase()}': {
type: 'ios.app',
- binaryPath: 'ios/build/Build/Products/${conf}-iphonesimulator/YOUR_APP.app',
+ binaryPath: 'ios/build/Build/Products/${conf}-iphonesimulator/example.app',
- build: 'xcodebuild -workspace ios/YOUR_APP.xcworkspace -scheme YOUR_APP -configuration ${conf} -sdk iphonesimulator -derivedDataPath ios/build'
+ build: 'xcodebuild -workspace ios/example.xcworkspace -scheme example -configuration ${conf} -sdk iphonesimulator -derivedDataPath ios/build'
},`}
</FlavorizedCodeBlock>
:::info
If your app uses [CocoaPods] (all modern React Native projects do since `0.60.0`), make sure
to run `pod install` in your `ios/` folder before building with Detox.
If your project doesn't use the pods, then you won't have any `YourApp.xcworkspace` in your iOS project directory.
You should search instead for something like `YourApp.xcodeproj` there, and adjust your build command accordingly:
<FlavorizedCodeBlock
language="diff"
header={' apps: {\n'}
flavors={['Debug', 'Release']}
>
{(conf) => `\
'ios.${conf.toLowerCase()}': {
type: 'ios.app',
binaryPath: 'ios/build/Build/Products/${conf}-iphonesimulator/example.app',
- build: 'xcodebuild -workspace ios/YOUR_APP.xcworkspace -scheme YOUR_APP -configuration ${conf} -sdk iphonesimulator -derivedDataPath ios/build'
+ build: 'xcodebuild -project ios/example.xcodeproj -scheme example -sdk -configuration ${conf} iphonesimulator -derivedDataPath ios/build'
},`}
</FlavorizedCodeBlock>
:::
[cocoapods]: https://cocoapods.org/
@@ -0,0 +1,94 @@
import CodeBlock from '@theme/CodeBlock';
<CodeBlock language="sh">
detox build --configuration {props.configurationName}
</CodeBlock>
If the build is failing, try out our [Troubleshooting](../../Troubleshooting.BuildingTheApp.md) section.
:::info
Detox CLI just executes the build command you specified in your Detox config (`.detoxrc.js`)
for a specific configuration. In the other words, it has no extra logic – it just takes the command and runs it,
nothing more and nothing less.
:::
<>
{props.debug && <div>
Since this is a debug configuration, you need to have React Native packager running in parallel before you start
Detox tests:
```bash
npm start
> react-native start
# #######
# ################
# ######### #########
# ######### ##########
# ######### ###### #########
# ##########################################
# ##### ##################### #####
# ##### ############## #####
# ##### ### ###### ### #####
# ##### ####### ####### #####
# ##### ########### ########### #####
# ##### ########################## #####
# ##### ########################## #####
# ##### ###################### ######
# ###### ############# #######
# ######### #### #########
# ######### #########
# ######### #########
# #########
#
#
# Welcome to Metro!
# Fast - Scalable - Integrated
```
</div>}
</>
Now you can run the starter test:
<CodeBlock language="sh">
detox test --configuration {props.configurationName}
</CodeBlock>
You should see something like:
```
FAIL e2e/starter.test.js (25.916 s)
Example
✕ should have welcome screen (662 ms)
✕ should show hello screen after tap (236 ms)
✕ should show world screen after tap (236 ms)
● Example › should have welcome screen
Test Failed: No elements found for “MATCHER(id == “welcome”)”
HINT: To print view hierarchy on failed actions/matches, use log-level verbose or higher.
9 |
10 | it('should have welcome screen', async () => {
> 11 | await expect(element(by.id('welcome'))).toBeVisible();
| ^
12 | });
13 |
14 | it('should show hello screen after tap', async () => {
at Object.toBeVisible (e2e/starter.test.js:11:45)
…
```
Although all the three tests are failing, this is exactly what we expect
(because you don't have elements with such IDs in your app).
Now you are ready to write your first test. Congratulations!
@@ -0,0 +1,85 @@
import CodeBlock from '@theme/CodeBlock';
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
To check if a specific Android virtual device (e.g. `Pixel_3a_API_30_x86`) is installed locally, run:
```bash
emulator -list-avds
```
You should see an output like:
```plain text
// highlight-next-line
Pixel_3a_API_30_x86
Pixel_API_30
```
:::tip
If you see `zsh: command not found` (or a similar message), please go back to
[Setting up the environment](../getting-started.mdx#setting-up-the-environment) section
where we were redirecting you to the official **React Native CLI Quickstart**, and make sure you
have completed it.
Provided you have `ANDROID_SDK_ROOT` (or `ANDROID_HOME`) environment variables
defined, using an explicit path to `emulator` should help:
<Tabs groupId="desktopOS">
<TabItem value="darwin" label="MacOS">
<CodeBlock language="bash">
$ANDROID_SDK_ROOT/emulator/emulator -list-avds
</CodeBlock>
</TabItem>
<TabItem value="linux" label="Linux">
<CodeBlock language="bash">
$ANDROID_SDK_ROOT/emulator/emulator -list-avds
</CodeBlock>
</TabItem>
<TabItem value="win32" label="Windows">
<CodeBlock language="plain text">
%ANDROID_HOME%\emulator\emulator -list-avds
</CodeBlock>
</TabItem>
</Tabs>
:::
If you don't see that AVD name, you might use another one from the list – just replace it in Detox config, e.g.:
```diff
emulator: {
type: 'android.emulator',
device: {
- avdName: 'Pixel_3a_API_30_x86',
+ avdName: 'Pixel_API_30',
},
},
```
If the output is completely blank, then you need to open Android Studio and [create a new virtual device (AVD)](https://developer.android.com/studio/run/managing-avds#createavd)
first. Experienced users might do that via [`avdmanager`](https://developer.android.com/studio/command-line/avdmanager), if Android Studio is not installed (e.g. on CI).
:::info
If you wish to use an attached Android device (via USB or wireless network), make sure it is available:
```bash
adb devices
```
If the device is properly connected, you should get an output like this:
```plain text
List of devices attached
2F6315NVPH device
```
Assuming the device is available (troubleshooting _adb_ issues is out of scope of this tutorial), you just
need to use `android.att.*` Detox configurations instead of `android.emu.*` where required.
:warning: If you have multiple devices connected, replace that loose regular expression (`adbName: '.*'`)
in your Detox config with a specific device name.
:::
@@ -0,0 +1,41 @@
To check if a specific device type (e.g. `iPhone 12`) is installed locally, run:
```bash
xcrun simctl list devicetypes
```
If it is available, you'll see it among the other device types in the output:
```plain text
== Device Types ==
iPhone 4s (com.apple.CoreSimulator.SimDeviceType.iPhone-4s)
iPhone 5 (com.apple.CoreSimulator.SimDeviceType.iPhone-5)
…
iPhone SE (2nd generation) (com.apple.CoreSimulator.SimDeviceType.iPhone-SE--2nd-generation-)
iPhone 12 mini (com.apple.CoreSimulator.SimDeviceType.iPhone-12-mini)
// highlight-next-line
iPhone 12 (com.apple.CoreSimulator.SimDeviceType.iPhone-12)
iPhone 12 Pro (com.apple.CoreSimulator.SimDeviceType.iPhone-12-Pro)
…
```
If there is no such device type, you can replace it with another from the list:
```diff
simulator: {
type: 'ios.simulator',
device: {
- type: 'iPhone 12',
+ type: 'iPhone 13 Pro',
},
},
```
:::tip
If the device type list is empty or you need a specific iOS version,
go to `Xcode > Preferences > Components` and install a proper Simulator version from the list:
![](../../img/xcode/install-simulator-runtime.png)
:::
@@ -0,0 +1,43 @@
1. Add in your Android project settings:
```diff title="android/settings.gradle"
+include ':detox'
+project(':detox').projectDir = new File(rootProject.projectDir, '../node_modules/detox/android/detox')
```
1. In your _root_ build script register `google()` as a repository lookup point in all projects:
```diff title="android/build.gradle"
allprojects {
repositories {
// ...
+ google()
}
}
```
If `allprojects` section doesn't exist, then add it.
1. In your app’s build script, add to `dependencies` section:
```diff title="android/app/build.gradle"
dependencies {
// ...
+ androidTestImplementation(project(path: ":detox"))
}
```
1. Stay in that file, just scroll down and add to the `defaultConfig` subsection:
```diff title="android/app/build.gradle"
android {
// ...
defaultConfig {
// ...
+ testBuildType System.getProperty('testBuildType', 'debug') // This will later be used to control the test apk build type
+ testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
+ missingDimensionStrategy 'detox', 'full'
}
}
```
@@ -0,0 +1,18 @@
1. Go to `node_modules/detox` and extract `Detox-ios-src.tbz`
![extracted detox-ios-src directory](../../img/xcode/extracted-ios-src.png)
1. Drag `Detox-ios-src/Detox.xcodeproj` into your Xcode project
![Detox inside Xcode project](../../img/xcode/drag-src-to-project.png)
1. Go to your project settings → **General** and add **Detox.framework** to **Frameworks, Libraries, and Embedded Content** (make sure **Embed & Sign** is selected under **Embed**)
![embed Detox](../../img/xcode/embed-detox-project.png)
:::caution
Apps should not be submitted to the App Store with the Detox framework linked. Follow this guide only to debug Detox issues in your project. Once finished, make sure to remove **Detox.framework** from your project.
:::
@@ -0,0 +1,29 @@
```json
{
"devices": {
"emulator": {
"type": "android.emulator",
"device": {
"avdName": "<e.g., Pixel_API_28>"
}
}
},
"apps": {
"android.debug": {
"type": "android.apk",
"binaryPath": "<path to your app binary built before>"
}
},
"configurations": {
// highlight-start
"android.manual": {
"device": "emulator",
"app": "android.debug",
"behavior": {
"launchApp": "manual"
}
}
// highlight-end
}
}
```
@@ -0,0 +1,29 @@
```json
{
"devices": {
"simulator": {
"type": "ios.simulator",
"device": {
"type": "<e.g., iPhone 12 Pro>"
}
}
},
"apps": {
"ios.debug": {
"type": "ios.app",
"binaryPath": "<path to your app binary built before>"
}
},
"configurations": {
// highlight-start
"ios.manual": {
"device": "simulator",
"app": "ios.debug",
"behavior": {
"launchApp": "manual"
}
}
// highlight-end
}
}
```
@@ -0,0 +1,56 @@
```plain text
18:26:07.024 detox[45214] i Waiting for you to manually launch your app in Android Studio.
Instrumentation class: com.wix.detox.test.test/com.example.DetoxTestAppJUnitRunner
Instrumentation arguments:
------------------------------------
Key | Value
------------------------------------
detoxServer | ws://localhost:8099
detoxSessionId | test
------------------------------------
Press any key to continue...
```
Now it is time to switch back to Android Studio. You’ll need to run your instrumentation runner with the said arguments,
this is why you should create a debug configuration of `Android Instrumented Tests` type similar to the one below:
![Android Debug Configuration - Android Instrumented Tests](../../img/android-studio-debug-configuration.png)
Make sure to put breakpoints at the points of interest before you start the app.
After the app is launched, go back to the Terminal where Detox is running and press any key.
As a result, you are expected to see a confirmation from Detox, e.g.:
```plain text
Found the app (com.wix.detox-example) with process ID = 16854. Proceeding...
```
Now the entire test will run as usual until it sends an action to the app, which gets trapped
in your breakpoint.
![Breakpoint is active](../../img/android-happy-debugging.png)
Happy debugging!
P.S. If you see this timeout error too often while debugging:
```plain text
Waited for the new RN-context for too long! (60 seconds)
If you think that’s not long enough, consider applying a custom Detox runtime-config in DetoxTest.runTests().
```
you can temporarily hack the timeout here:
```diff title="detox/android/detox/src/main/java/com/wix/detox/config/DetoxConfig.kt"
package com.wix.detox.config
class DetoxConfig {
@JvmField var idlePolicyConfig: DetoxIdlePolicyConfig = DetoxIdlePolicyConfig()
- @JvmField var rnContextLoadTimeoutSec = 60
+ @JvmField var rnContextLoadTimeoutSec = Int.MAX_VALUE
fun apply() {
idlePolicyConfig.apply()
```
@@ -0,0 +1,34 @@
```plain text
18:26:07.024 detox[45214] i Waiting for you to manually launch your app in Xcode.
Make sure to pass the launch arguments listed below:
-detoxServer ws://localhost:8099
-detoxSessionId com.wix.detox-example
Press any key to continue...
```
You’ll need to run your app with the said arguments from Xcode:
![Xcode - Edit Schema - Arguments tab](../../img/xcode/edit-schema-arguments.png)
Before you launch the app, make sure to [put breakpoints](https://developer.apple.com/documentation/xcode/setting-breakpoints-to-pause-your-running-app) at the points of interest, e.g.:
![put a breakpoint in the native code](../../img/xcode/putting-a-breakpoint.png)
Launch the app with the debugger attached:
![launching the app](../../img/xcode/launch-app-with-debugger.png)
The moment you see the app is idle, go back to the Terminal where Detox is running
and press any key. If you wish to terminate the process for some reason, use Ctrl+C.
In a couple of seconds you are expected to see a confirmation from Detox, e.g.:
```plain text
Found the app (com.wix.detox-example) with process ID = 16854. Proceeding...
```
Now the entire test will run as usual until it sends an action to the app, which gets trapped
in your breakpoint.
Happy debugging!
@@ -0,0 +1,21 @@
:::caution Note
Expo support with Detox is entirely a community driven effort. We have no specific support in Detox for Expo applications (ejected or otherwise).
:::
There are a few resources on the Internet covering how to set up Detox with Expo apps:
- <https://github.com/fschoenfeldt/clean-expo-detox-testing>
- <https://toshev.medium.com/setting-up-detox-with-a-expo-managed-react-native-project-89342dce4df>
- <https://blog.expo.dev/testing-expo-apps-with-detox-and-react-native-testing-library-7fbdbb82ac87>
Unfortunately, we have no capacity to maintain this direction and hold no responsibility for content and
quality of the mentioned or another available resources.
For support on how to use Detox with Expo, you should contact the Expo team or the Expo community. If you
are seeing an issue, it is most likely not an issue with Detox itself, but with the Expo runtime or with
an incorrect Detox setup. Genuine issues with Detox can be submitted to [our issue tracker](https://github.com/wix/Detox/issues)
as usual.
The tutorial below is useful, but is **not enough** to complete the setup with Expo.
@@ -0,0 +1,13 @@
:::caution Note
At the moment, Detox does not support non-React Native apps on **Android** due to the blocking issues:
* [Restore support for pure-native/hybrid Projects](https://github.com/wix/Detox/issues/2543)
* [cannot be cast to com.facebook.react.ReactApplication](https://github.com/wix/Detox/issues/1220)
* [native android app Process crashes](https://github.com/wix/Detox/issues/1093)
:::
However, native iOS apps are expected to work fine with Detox, and if that's your case, the tutorial
below will help you in equal measure.
@@ -1,13 +1,10 @@
---
id: running-on-ci
slug: guide/running-on-ci
title: Running on CI
sidebar_label: Running on CI
---
# Preparing for CI
## Running on CI
:::danger Disclaimer
> Disclaimer: This guide is focused on iOS (i.e. lacking info about Android) and is generally out of date.
This guide is outdated.
:::
When your test suite is finally ready, it should be set up to run automatically on your CI server on every git push. This will alert you if new changes to the app break existing functionality.
@@ -16,58 +13,37 @@ Running Detox on CI is not that different from running it locally. There are two
- You should test a release build rather than a debug build
- Tell Detox to shut down the simulator when test is over
### Step 1: Prepare a Release Configuration for Your App
## Step 1: Prepare a Release Configuration for Your App
We will need to create a [release device configuration for Detox](APIRef.Configuration.md#device-configurations) inside `package.json` under the `detox` section.
We will need to create a release app configuration for Detox – follow [the previous tutorial](building-with-detox.mdx)
if you haven't completed it already.
**Example:**
```json
"detox": {
"devices": {
"simulator": {
"type": "ios.simulator",
"device": {
"type": "iPhone 12 Pro Max"
}
}
},
"apps": {
"ios.release": {
"type": "ios.app",
"binaryPath": "ios/build/Build/Products/Release-iphonesimulator/example.app",
"build": "xcodebuild -project ios/example.xcodeproj -scheme example -configuration Release -sdk iphonesimulator -derivedDataPath ios/build",
}
},
"configurations": {
"ios.sim.release": {
"device": "simulator",
"app": "ios.release"
}
}
}
```
> TIP: Notice that the name `example` above should be replaced with your actual project name.
### Step 2: Add `build` and `test` Commands to Your CI Script
## Step 2: Add `build` and `test` Commands to Your CI Script
Assuming your CI is executing some sort of shell script, add the following commands that should run inside the project root:
```sh
```bash
detox build --configuration ios.sim.release
detox test --configuration ios.sim.release --cleanup
detox test --configuration ios.sim.release
```
> **Tip:** Adding `--cleanup` to the test command will make sure detox exits cleanly by shutting down the simulator when the test is over.
:::tip
### Running Android Tests on CI
Make sure to shut down the simulator when your tests are over.
Setting up a CI environment capable of running Android tests isn’t as trivial. Fortunately, we’ve written all about it in a [blogpost on medium!](https://medium.com/wix-engineering/how-to-execute-android-ui-tests-on-ci-and-stay-alive-eb9089d88c1f)
:::
### Appendix
## Running Android Tests on CI
#### • Running Detox on [Travis CI](https://travis-ci.org/)
Setting up a CI environment capable of running Android tests isn’t as trivial.
Fortunately, we’ve written all about it in a [blogpost on medium!](https://medium.com/wix-engineering/how-to-execute-android-ui-tests-on-ci-and-stay-alive-eb9089d88c1f)
Also, check out the guide on how to [prepare Android emulators for CI](../Guide.CI.AndroidEmulator.md).
## Appendix
### • Running Detox on [Travis CI](https://travis-ci.org/)
Detox’s own build is running on Travis, check out Detox’s [`.travis.yml`](https://github.com/wix/Detox/tree/master/.travis.yml) file to see how it’s done.
@@ -103,7 +79,7 @@ script:
```
#### • Running Detox on [Bitrise](https://www.bitrise.io/)
### • Running Detox on [Bitrise](https://www.bitrise.io/)
Bitrise is a popular CI service for automating React Native apps. If you are looking to get started with Bitrise, check out [this](https://blog.bitrise.io/post/how-to-set-up-a-react-native-app-on-bitrise) guide.
@@ -178,7 +154,7 @@ workflows:
after_run: []
```
#### • Running Detox on [GitLab CI](https://docs.gitlab.com/ee/ci/README.html) - Android Only
### • Running Detox on [GitLab CI](https://docs.gitlab.com/ee/ci/README.html) - Android Only
GitLab is also a popular git management service which also include a built-in CI system. They provide free runner up to 2000 minutes for private projects, however, the runners provided by them cannot be used to run Detox due to the lack of KVM support (in order to run Android Emulators). You can, instead, [create your own runner](https://docs.gitlab.com/ee/ci/runners/README.html) with KVM support. Some example of cloud providers offering this are: [Digital Ocean](https://www.digitalocean.com/products/droplets/), AWS (with [C5 instance types](https://aws.amazon.com/ec2/instance-types/c5/)), [Google Cloud](https://cloud.google.com/compute/docs/instances/enable-nested-virtualization-vm-instances) and [Azure](https://docs.microsoft.com/en-us/azure/virtual-machines/windows/nested-virtualization)
@@ -1,35 +1,36 @@
---
id: writing-first-test
slug: introduction/writing-first-test
title: Writing Your First Test
sidebar_label: Writing Your First Test
---
# Writing Your First Test
## Writing Your First Test
:::danger Disclaimer
This article is outdated and it suggests using a deprecated tool.
We're looking for contributors who could provide a beginner-friendly
explanation on how to start writing tests.
:::
This tutorial assumes you’ve already installed Detox successfully on a working React Native project.
### Detox Recorder
## Detox Recorder
Check out [Detox Recorder](https://github.com/wix/DetoxRecorder), our tool for recording tests directly from your device.
### Step 1: Prepare a JavaScript File to Hold Your Scenario (Spec)
## Step 1: Prepare a JavaScript File to Hold Your Scenario (Spec)
Every Detox test scenario is usually placed in its own JavaScript file. If you’ve followed the [installation tutorial](Introduction.GettingStarted.md), these files are located in `/e2e/*.spec.js` under your React Native project root. Feel free to place these files wherever you like, this directory structure is just a recommendation.
Every Detox test scenario is usually placed in its own JavaScript file. If you’ve followed the [installation tutorial](getting-started.mdx), these files are located in `/e2e/*.spec.js` under your React Native project root. Feel free to place these files wherever you like, this directory structure is just a recommendation.
If you’re using Mocha as your test runner, these files will simply be executed one by one when you run your tests.
If you’ve followed the installation tutorial, you should already have `firstTest.spec.js` as a placeholder to start from.
### Step 2: Decide how to Reset Your App for the Beginning of the Scenario
## Step 2: Decide how to Reset Your App for the Beginning of the Scenario
In order to start the scenario from a predictable app state and reset the state from any previous scenarios that may have been running, it’s customary to start the scenario by restarting the app.
The fastest way to reset is by calling `await device.reloadReactNative();`. This is equivalent to pressing CMD+R in the simulator window - it will just reload the React Native bundle. You can find other alternatives that may be slower but more thorough [here](APIRef.DeviceObjectAPI.md).
The fastest way to reset is by calling `await device.reloadReactNative();`. This is equivalent to pressing CMD+R in the simulator window - it will just reload the React Native bundle. You can find other alternatives that may be slower but more thorough [here](../api/device.md).
Our scenario is made from multiple different test cases (`it()` clauses). We usually want to reset before each one is running. This can be accomplished by placing the reset logic inside a `beforeEach()` clause.
### Step 3: Add `testID`s to Your App to Assist in Matching Elements
## Step 3: Add `testID`s to Your App to Assist in Matching Elements
Most test cases start by finding a UI element on screen (_matching_) and performing some user interaction on it (_action_). To assist in finding the correct UI element, it’s recommended to mark it in some way. The best practice is to use the [`testID`](https://facebook.github.io/react-native/docs/view.html#testid) prop for this purpose. This means we’ll modify the app code and add these props to various elements.
@@ -43,23 +44,23 @@ Note that not all React components support this prop. Most of the built-in nativ
</View>
```
### Step 4: Match an Element and Perform an Action
## Step 4: Match an Element and Perform an Action
Choose a method to match your element, the various alternatives are documented [here](APIRef.Matchers.md). You will most likely be relying on `testID` which means our matching code will look like `element(by.id('MyUniqueId123'))`.
Choose a method to match your element, the various alternatives are documented [here](../api/matchers.md). You will most likely be relying on `testID` which means our matching code will look like `element(by.id('MyUniqueId123'))`.
Choose an action to perform on the element, the various alternatives are documented [here](APIRef.ActionsOnElement.md). If we have a button, a `tap` is probably what you’re looking for, resulting in this code:
Choose an action to perform on the element, the various alternatives are documented [here](../api/actions.md). If we have a button, a `tap` is probably what you’re looking for, resulting in this code:
```jsx
await element(by.id('MyUniqueId123')).tap();
```
### Step 5: Set an Expectation on the Result
## Step 5: Set an Expectation on the Result
After performing the action, the app will most likely do something. The process might also take a little time - for example if we’re logging in, there would be a server request. The great thing about detox is that you’re not supposed to worry about synchronization and how much time actions take. Detox will monitor the app and continue to the next line in your test only when the app completes pending operations and becomes idle.
The most natural expectation is to verify that some UI element has eventually appeared on screen as a result. Like before, we’ll need to match this element first. We can keep using `testID` for this purpose with `element(by.id('AnotherUniqueId456'))`.
The various available expectations are documented [here](APIRef.Expect.md). If we want to make sure an element is visible, we’ll get:
The various available expectations are documented [here](../api/expect.md). If we want to make sure an element is visible, we’ll get:
```jsx
await expect(element(by.id('AnotherUniqueId456'))).toBeVisible();
@@ -67,14 +68,12 @@ await expect(element(by.id('AnotherUniqueId456'))).toBeVisible();
Note that the visibility matcher makes sure the element is actually visible on screen (at least 75% of it to be exact). If it appears under the fold (e.g. the user has to scroll to see it), this specific matcher will fail.
### Step 6: Rinse and Repeat
## Step 6: Rinse and Repeat
Create more complicated test cases by stringing actions and expectations one after the other. Explore the rest of the API to see what other things you can do in your tests.
Add more test cases to your file by adding `it()` clauses. Add new scenarios by adding new `*.spec.js` files.
### Step 7: Run Your Tests and Make Sure They Pass
## Step 7: Run Your Tests and Make Sure They Pass
This is usually done by running `detox test` in terminal. If your test is failing, and you don’t understand why, take a look at the [troubleshooting tutorial](Troubleshooting.RunningTests.md).
How do you continue from here? Read about the various recommended workflows with detox documented [here](Introduction.Workflows.md). Hopefully you’ll find a workflow that makes sense moving forward and complements your development process.
This is usually done by running `detox test` in terminal. If your test is failing, and you don’t understand why, take a look at the [troubleshooting tutorial](../Troubleshooting.RunningTests.md).
+6 -1
View File
@@ -7,7 +7,7 @@ const darkCodeTheme = require('prism-react-renderer/themes/dracula');
/** @type {import('@docusaurus/types').Config} */
const config = {
title: 'Detox',
tagline: 'Gray box end-to-end testing and automation framework for mobile apps',
tagline: 'Gray box end-to-end testing and automation framework for React Native apps',
url: 'https://wix.github.io',
baseUrl: '/Detox/',
onBrokenLinks: 'throw',
@@ -123,6 +123,11 @@ const config = {
}
]
},
docs: {
sidebar: {
autoCollapseCategories: true,
},
},
prism: {
theme: lightCodeTheme,
darkTheme: darkCodeTheme
+49 -34
View File
@@ -18,42 +18,44 @@ const sidebars = {
type: 'category',
label: 'Introduction',
items: [
'getting-started',
'ios-dev-env',
'android-dev-env',
'ios',
'android',
'writing-first-test',
'how-detox-works',
'design-principles',
'workflows'
'introduction/getting-started',
'introduction/building-with-detox',
'introduction/writing-first-test',
'introduction/preparing-for-ci',
'introduction/debugging'
]
},
{
type: 'category',
label: 'Configuration',
items: [
'config/overview',
'config/devices',
'config/apps',
'config/artifacts',
'config/behavior',
'config/logger',
'config/session',
'config/testRunner',
]
},
{
type: 'category',
label: 'API Reference',
items: [
'detox-cli',
'configuration',
'detox-object-api',
'device-object-api',
'test-lifecycle',
'matchers',
'actions-on-element',
'expect',
'launch-args',
'mocking-open-with-url',
'mocking-user-notifications',
'mocking-user-activity',
'artifacts',
'screenshots'
'api/detox-cli',
'api/device',
'api/matchers',
'api/actions',
'api/expect',
'api/logger',
'api/internals',
]
},
{
type: 'category',
label: 'Troubleshooting',
items: [
'troubleshooting',
'building-the-app',
'running-tests',
'synchronization',
@@ -64,20 +66,33 @@ const sidebars = {
type: 'category',
label: 'Guides',
items: [
'running-locally',
'developing-while-writing-tests',
'running-on-ci',
'debugging-in-xcode',
'debugging-in-android-studio',
'mocking',
'migration',
'jest',
'parallel-test-execution',
'third-party-drivers',
'expo',
'guide/genymotion-cloud',
'guide/taking-screenshots',
'mocking',
'launch-args',
'mocking-open-with-url',
'mocking-user-notifications',
'mocking-user-activity',
'developing-while-writing-tests',
'android-dev-env',
'proguard-configuration',
'uninstalling',
]
},
{
type: 'category',
label: 'Articles',
items: [
'articles/design-principles',
'articles/how-detox-works',
'articles/third-party-drivers',
]
},
{
type: 'doc',
id: 'migration',
},
{
type: 'doc',
label: 'Contributing',
@@ -0,0 +1,18 @@
import React from 'react';
import CodeBlock from '@theme/CodeBlock';
export default function FlavorizedCodeBlock({
flavors,
children,
header,
footer,
...codeBlockProps
}) {
return (
<CodeBlock {...codeBlockProps}>
{header}
{flavors.map(children).join('\n')}
{footer}
</CodeBlock>
);
}
+11 -9
View File
@@ -3,15 +3,6 @@ import clsx from 'clsx';
import styles from './HomepageFeatures.module.css';
const FeatureList = [
{
title: 'Supports Different Test Runners',
Svg: require('../../static/img/test-runner.svg').default, // taken from: https://uxwing.com/testing-icon/
description: (
<>
Use Jest or Mocha as the test runner (spoiler: we have our favorite).
</>
),
},
{
title: 'Cross Platform',
Svg: require('../../static/img/cross-platform.svg').default, // taken from: https://uxwing.com/magic-icon/
@@ -58,6 +49,17 @@ const FeatureList = [
</>
),
},
{
title: 'Test Runner Agnostic',
Svg: require('../../static/img/test-runner.svg').default, // taken from: https://uxwing.com/testing-icon/
description: (
<>
Detox provides a set of APIs to use with any test runner or without it.
It comes with <a href="https://jestjs.io" target="_blank" rel="noopener noreferrer">Jest</a> integration
out of the box.
</>
),
},
];
function Feature({Svg, title, description}) {
+1
View File
@@ -14,6 +14,7 @@
--ifm-color-primary-lighter: #8859c9;
--ifm-color-primary-lightest: #9f6de5;
--ifm-code-font-size: 95%;
--docusaurus-highlighted-code-line-bg: #d9e5f6;
}
.footer--dark {