Skip to main content
Version: 19.x

Detox Object API

The detox Object

detox is globally available in every test file, though currently it is only used in the setup/init file.

NOTE: detox is test runner independent, and we encourage you to choose your own test runner, but for the sake of demonstration we will use mocha’s syntax.

Methods

detox.init()

The setup phase happens inside detox.init(). This is the phase where detox reads its configuration, starts a server, loads its expectation library and starts a simulator.

If you’re using mocha, in your init.js add:

const detox = require('detox');

before(async () => {
await detox.init();
});
Explicit imports during initialization

Detox exports device, expect, element, by and waitFor as globals by default, if you want to control their initialization manually, set init detox with initGlobals set to false. This is useful when during E2E tests you also need to run regular expectations in node. jest Expect for instance, will not be overridden by Detox when this option is used.

const detox = require('detox');

before(async () => {
await detox.init(undefined, {initGlobals: false});
});

Then import them manually:

const {device, expect, element, by, waitFor} = require('detox');

Use this example for initial setup

Reusing existing app

By default await detox.init(); will uninstall and install the app. If you wish to reuse the existing app for a faster run, add {reuse: true} param to your init.

before(async () => {
await detox.init(undefined, {reuse: true});
});

detox.beforeEach()

This method should be called at the start of every test to let Detox’s artifacts lifecycle know it is the time to start recording logs and videos, or to take another beforeEach.png screenshot. Although this is one of usage of beforeEach, Detox does not limit itself to this usage and may utilize calls to beforeEach for additional purposes in the future.

declare function beforeEach(testSummary: {
title: string;
fullName: string;
status: 'running';
})

Usually, you are not supposed to write own implementation of this call, instead rely on Detox in-house adapters for mocha and jest as in the examples. It should alleviate transitions to newer Detox versions for you as the chances are that API specification won’t prove itself as sufficient and it may undergo rewrites and extensions.

NOTE: If you are implementing support for a test runner different from Mocha and Jest, please keep in mind that pending (also known as skipped) tests should not trigger detox.beforeEach() at all, neither detox.afterEach(). The rule of thumb is either you guarantee you call them both, or you don’t call anyone.

detox.afterEach()

You are expected to call this method only after the test and all its inner afterEach()-es complete. Besides passing test title and full name, you should pay heed on delivering a valid status field: failed or passed. If the test has another status (e.g. skipped), please comply to the note above in detox.beforeEach() or use one of these two values as a fallback.

declare function afterEach(testSummary: {
title: string;
fullName: string;
status: 'failed' | 'passed';
})

Normally, you are not supposed to write own implementation of this call, as mentioned earlier in the detox.beforeEach() documentation.

detox.cleanup()

The cleanup phase should happen after all the tests have finished. This is the phase where detox server shuts down. The simulator will also shut itself down if --cleanup flag is added to detox test

If you’re using mocha, in your init.js add:

after(async () => {
await detox.cleanup();
});

detox.traceCall()

⚠️ Beta

Trace a subprocess of your test’s runtime such that it would leave traces inside the Timeline artifact, for a later inspection.

Example:

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

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

⚠️ 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:

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.