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()
detox.beforeEach()
detox.afterEach()
detox.cleanup()
detox.traceCall()
detox.trace.startSection(), detox.trace.endSection()
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, neitherdetox.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:
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.