Skip to main content
Version: Next

Device

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:

const { device } = require('detox');

It enables control over the current attached device.

Public Properties

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

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

Access the launch-arguments predefined by the user in preliminary, static scopes such as the Detox configuration file and command-line arguments. This access allows, through dedicated methods, for both value-querying and modification:

// Modify some of the predefined arguments:
device.appLaunchArgs.modify({
mockServerPort: 1234,
});
// Retrieve the arguments:
device.appLaunchArgs.get(); // ==> { mockServerPort: 1234 }
// Reset (i.e. remove all arguments):
device.appLaunchArgs.reset();

In multi-app environments, you might want to persist your values between device.selectApp(name) calls:

device.appLaunchArgs.modify({ transientArg: 'value' });
device.appLaunchArgs.shared.modify({
permanentMockServerPort: 1234,
};

device.appLaunchArgs.get(); // ==> { permanentMockServerPort: 1234, transientArg: 'value' }
device.appLaunchArgs.shared.get(); // ==> { permanentMockServerPort: 1234 }

await device.selectApp('anotherApp');
device.appLaunchArgs.get(); // ==> { permanentMockServerPort: 1234 }
device.appLaunchArgs.reset();
device.appLaunchArgs.get(); // ==> { permanentMockServerPort: 1234 }
device.appLaunchArgs.shared.reset();
device.appLaunchArgs.get(); // ==> {}

This is the most flexible way of editing the launch arguments. Refer to the launch arguments guide for complete details.

Methods

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 to discover how to define multiple apps with different names.

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)

Launch the app defined in the current configuration.

params—object, containing one of more of the following keys and values:

1. newInstance—Launching a New Instance of the App

Terminate the app and launch it again.

If set to false, the device will try to resume the app (e.g. bring from foreground to background). If the app isn’t running, it will launch a new instance nonetheless. Default is false.

await device.launchApp({newInstance: true});

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.

await device.launchApp({permissions: {calendar: 'YES'}});

Detox uses AppleSimUtils and xcrun simctl to implement this functionality for iOS simulators. Please make sure you have the most recent version of both tools installed, since we rely on their latest versions.

Supported Permissions
PermissionValuesNotes
locationalways / inuse / never / unsetinuse - provides location access only when the app is in use
contactsYES / NO / unset / limitedlimited - grants limited access to contacts
photosYES / NO / unset / limitedlimited - grants limited access to photos
calendarYES / NO / unset
cameraYES / NO / unset
medialibraryYES / NO / unset
microphoneYES / NO / unset
motionYES / NO / unset
remindersYES / NO / unset
siriYES / NO / unset
notificationsYES / NO / unsetRequires AppleSimUtils; unsupported by simctl
healthYES / NO / unsetRequires AppleSimUtils; unsupported by simctl
homekitYES / NO / unsetRequires AppleSimUtils; unsupported by simctl
speechYES / NO / unsetRequires AppleSimUtils; unsupported by simctl
faceidYES / NO / unsetRequires AppleSimUtils; unsupported by simctl
userTrackingYES / NO / unsetRequires AppleSimUtils; unsupported by simctl

Check Detox's own test suite for usage examples.

3. url—Launching with URL

Launches the app with the specified URL to test your app’s deep link handling mechanism.

await device.launchApp({url});
await device.launchApp({url, newInstance: true}); // Launch a new instance of the app
await device.launchApp({url, newInstance: false}); // Reuse existing instance

Read more here. Go back to subsection 1 to read about the full effect of the newInstance argument.

4. userNotification—Launching with User Notifications

Launches with the specified user notification.

await device.launchApp({userNotification});
await device.launchApp({userNotification, newInstance: true}); // Launch a new instance of the app
await device.launchApp({userNotification, newInstance: false}); // Reuse existing instance

Read more here. Go back to subsection 1 to read about the full effect of the newInstance argument.

5. userActivity—Launch with User Activity (iOS Only)

Launches the app with the specified user activity.

await device.launchApp({userActivity: activity});
await device.launchApp({userActivity: activity, newInstance: true}); //Launch a new instance of the app
await device.launchApp({userActivity: activity, newInstance: false}); //Reuse existing instance

Read more in here. Go back to subsection 1 to read about the full effect of the newInstance argument.

6. delete—Delete and Reinstall Application Before Launching

Before launching the application, it is uninstalled and then reinstalled.

A flag that enables relaunching into a fresh installation of the app (it will uninstall and install the binary). Default is false.

await device.launchApp({delete: true});

7. launchArgs—Additional Process Launch Arguments

Launches the app on the device with on-site, user-specified launch arguments:

await device.launchApp({
launchArgs: {
arg1: 1,
arg2: "2",
}
});

This is the most explicit and straightforward way of setting launch arguments. Refer to the launch arguments guide for a complete overview on app launch arguments.

8. disableTouchIndicators—Disable Touch Indicators (iOS Only)

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)

Launch the app with a specific system language

Information about accepted values can be found here.

await device.launchApp({
languageAndLocale: {
language: "es-MX",
locale: "es-MX"
}
});

With this API, you can run sets of E2E tests per language. For example:

describe.each([
['es-MX'], ['fr-FR'], ['pt-BR'],
])(`Test suite (locale: %s)`, (locale) => {
beforeAll(async () => {
await device.launchApp({
newInstance: true,
languageAndLocale: {
language: locale,
locale
}
});
});

test('some description', async () => {
// …
});
});

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().

await device.launchApp({
newInstance: true,
launchArgs: { detoxEnableSynchronization: 0 }
});

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.

Note that due to the complexity of reg-exps and interoperability concerns, the implementation is fairly sensitive to the format of the string of urls. Please do your best to follow the example below:

await device.launchApp({
newInstance: true,
launchArgs: { detoxURLBlacklistRegex: '\\("^http://192\.168\.1\.253:\\d{4}/.*","https://e\.crashlytics\.com/spi/v2/events"\\)' },
});

12. detoxDisableWebKitSecurity—Disable WebKit Security (iOS Only)

Disables WebKit security on iOS. Default is false.

This is useful for testing web views with iframes that loads CORS-protected content.

Important

Some pages may not load correctly when WebKit security is disabled (for example, PCI DSS-compliant pages). Disabling WebKit security may cause errors when loading pages that have strict security policies.

await device.launchApp({
launchArgs: { detoxDisableWebKitSecurity: true }
});

device.terminateApp()

By default, terminateApp() with no params will terminate the app file defined in the current configuration.

To terminate another app, specify its bundle id

await device.terminateApp('other.bundle.id');

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. Check out Detox’s own test suite

await device.sendToHome();
await device.launchApp({newInstance: false});
// app returned from background, do stuff

Check out Detox’s own test suite

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.

**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.

device.installApp()

By default, installApp() with no params will install the app file defined in the current configuration.

To install another app, specify its path

await device.installApp('path/to/other/app');

device.uninstallApp()

By default, uninstallApp() with no params will uninstall the app defined in the current configuration.

To uninstall another app, specify its bundle id

await device.uninstallApp('other.bundle.id');

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 section. Check out Detox’s own test suite

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 section. Check out Detox’s own test suite

device.sendUserActivity(params) iOS Only

Mock handling of received user activity when app is in foreground. Read more in Mocking User Activity section. Check out Detox’s own test suite

device.setOrientation(orientation)

Takes "portrait" or "landscape" and rotates the device to the given orientation.

Note: Setting device orientation is only supported for iPhone devices, or for apps declared as requiring full screen on iPad. For all other cases, the current test will be failed.

Check out Detox’s own test suite.

device.setLocation(lat, lon)

Sets the simulator/emulator location to the given latitude and longitude.

On iOS setLocation depends on xcrun simctl, and we recommend using its latest version.

On Android setLocation will work with both Android Emulator (bundled with Android development tools) and Genymotion. The correct permissions must be set in your app manifest.

await device.setLocation(32.0853, 34.7818);

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.

This API is useful for cases where test assertions must be made in an area of your application where it is okay for it to ever remain partly busy (e.g. due to an endlessly repeating on-screen animation). However, using it inherently suggests that you are likely to resort to applying sleep()’s in your test code - testing that area, which is not recommended and can never be 100% stable. Therefore, as a rule of thumb, test code running "inside" a sync-disabled mode must be reduced to the bare minimum.

Note: Synchronization is enabled by default, and it gets re-enabled on every launch of a new instance of the app.

await device.disableSynchronization();

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().

⚠️ Note: Making this call would resume synchronization instantly, having its returned promise only resolve when the app becomes idle again. In other words, this must only be called after you navigate back to "the safe zone", where the app should be able to eventually become idle again, or it would remain suspended "forever" (i.e. until a safeguard time-out expires).

await device.enableSynchronization();

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 named detoxURLBlacklistRegex (as explained here).

await device.setURLBlacklist(['.*127.0.0.1.*', '.*my.ignored.endpoint.*']);

device.resetContentAndSettings() iOS Only

Resets the Simulator to clean state (like the Simulator > Reset Content and Settings... menu item), especially removing previously set permissions.

await device.resetContentAndSettings();

device.getPlatform()

Returns the current device, ios or android.

if (device.getPlatform() === 'ios') {
await expect(loopSwitch).toHaveValue('1');
}

device.tap(point, shouldIgnoreStatusBar)

Perform a tap at arbitrary coordinates on the device's screen.

tap parameters

  • point — Coordinates in the element's coordinate space (default value: {x: 100, y: 100}, platforms: Android & IOS)
  • shouldIgnoreStatusBar — Coordinates will be measured starting from under the status bar (default value: true, platform: Android)

tap examples


await device.tap();
await device.tap({ x: 100, y: 150 }, false);
await device.tap({ x: 100, y: 150 });
await device.tap(false);

device.longPress(point, duration, shouldIgnoreStatusBar)

Perform a long press at arbitrary coordinates on the device's screen. Custom press duration if needed.

longPress parameters

  • point — Coordinates in the element's coordinate space (default value: {x: 100, y: 100}, platforms: Android & IOS)
  • duration — Custom press duration time, in milliseconds. (default values: Android: Standard long-press duration. IOS: 1000 milliseconds, platforms: Android & IOS)
  • shouldIgnoreStatusBar — Coordinates will be measured starting from under the status bar (default value: true, platform: Android)

longPress examples


await device.longPress();
await device.longPress({ x: 100, y: 150 }, 2000, false);
await device.longPress({ x: 100, y: 150 }, 2000);
await device.longPress(2000, false);
await device.longPress({ x: 100, y: 150 }, false);
await device.longPress({ x: 100, y: 150 });
await device.longPress(2000);
await device.longPress(false);

device.takeScreenshot([name])

Takes a screenshot of the device. For full details on taking screenshots with Detox, refer to the screen-shots guide.

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 the artifacts' folder upon the completion of the current test. The file can be opened later in Xcode 12.0 and above. See Xcode 12 Release notes: #57933113 for more details.

The name parameter is optional — by default, it equals to capture.

test('Capture view hierarchy', async () => {
const temporaryArtifactPath = await device.captureViewHierarchy('myElements');

// The temporary path will remain valid until the test completion.
// Afterwards, the artifact will be moved, e.g.:
// * on success, to: <artifacts-location>/✓ Capture view hierarchy/myElements.viewhierarchy
// * on failure, to: <artifacts-location>/✗ Capture view hierarchy/myElements.viewhierarchy
});

device.generateViewHierarchyXml([shouldInjectTestIds])

Generates a view hierarchy XML of the currently opened application. The XML is returned as a string.

The shouldInjectTestIds parameter is optional and defaults to false. When set to true, Detox will attempt to inject testID attributes into the XML for each element if undefined.

const viewHierarchyXml = await device.generateViewHierarchyXml();

device.shake() iOS Only

Simulate shake

device.setBiometricEnrollment(bool) iOS Only

Toggles device enrollment in biometric authentication (Touch ID or Face ID).

await device.setBiometricEnrollment(true);
// or
await device.setBiometricEnrollment(false);

device.matchFace() iOS Only

Simulates the success of a face match via Face ID

device.unmatchFace() iOS Only

Simulates the failure of face match via Face ID

device.matchFinger() iOS Only

Simulates the success of a finger match via Touch ID

device.unmatchFinger() iOS Only

Simulates the failure of a finger match via Touch ID

device.clearKeychain() iOS Only

Clears the device keychain

device.setStatusBar() iOS Only

Override simulator’s status bar. Available options:

await device.setStatusBar({
time: "12:34",
// Set the date or time to a fixed value.
// If the string is a valid ISO date string it will also set the date on relevant devices.
dataNetwork: "wifi",
// If specified must be one of 'hide', 'wifi', '3g', '4g', 'lte', 'lte-a', 'lte+', '5g', '5g+', '5g-uwb', or '5g-uc'.
wifiMode: "failed",
// If specified must be one of 'searching', 'failed', or 'active'.
wifiBars: "2",
// If specified must be 0-3.
cellularMode: "searching",
// If specified must be one of 'notSupported', 'searching', 'failed', or 'active'.
cellularBars: "3",
// If specified must be 0-4.
operatorName: "A1",
// Set the cellular operator/carrier name. Use '' for the empty string.
batteryState: "charging",
// If specified must be one of 'charging', 'charged', or 'discharging'.
batteryLevel: "50",
// If specified must be 0-100.
});

device.resetStatusBar() iOS Only

Resets any override in simulator’s status bar.

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

Clear a reversed TCP-port (e.g. previously set using device.reverseTcpPort()).

device.pressBack() Android Only

Simulate press back button.

await device.pressBack();

device.getUiDevice() Android Only

Exposes UiAutomator’s UiDevice API. 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.

UiDevice’s autogenerated code