# Detox
# Detox
Extends Helper
This is a wrapper on top of Detox (opens new window) library, aimied to unify testing experience for CodeceptJS framework. Detox provides a grey box testing for mobile applications, playing especially good for React Native apps.
Detox plays quite differently from Appium. To establish detox testing you need to build a mobile application in a special way to inject Detox code. This why Detox is grey box testing solution, so you need access to application source code, and a way to build and execute it on emulator.
Comparing to Appium, Detox runs faster and more stable but requires an additional setup for build.
# Setup
Build an application (opens new window) using
detox build
command.Install CodeceptJS (opens new window) and detox-helper:
npm i @codeceptjs/detox-helper --save
Detox configuration is required in package.json
under detox
section.
If you completed step 1 and step 2 you should have a configuration similar this:
"detox": {
"configurations": {
"ios.sim.debug": {
"device": "simulator",
"app": "ios.debug"
}
},
"apps": {
"ios.debug": {
"type": "ios.app",
"binaryPath": "../test/ios/build/Build/Products/Debug-iphonesimulator/MyTestApp.app",
"build": "xcodebuild -workspace ../test/ios/MyTestApp.xcworkspace -scheme MyTestApp -configuration Debug -sdk iphonesimulator -derivedDataPath ../test/ios/build"
}
},
"devices": {
"simulator": {
"type": "ios.simulator",
"device": {
"type": "iPhone 15"
}
}
}
}
# Configuration
Besides Detox configuration, CodeceptJS should also be configured to use Detox.
In codecept.conf.js
enable Detox helper:
helpers: {
Detox: {
require: '@codeceptjs/detox-helper',
configuration: '<detox-configuration-name>',
}
}
It's important to specify a package name under require
section and current detox configuration taken from package.json
.
Options:
configuration
- a detox configuration name. Required.reloadReactNative
- should be enabled for React Native applications.reuse
- reuse application for tests. By default, Detox reinstalls and relaunches app.registerGlobals
- (default: true) Register Detox helper functionsby
,element
,expect
,waitFor
globally.url
- URL to open via deep-link each time the app is launched (android) or immediately afterwards (iOS). Useful for opening a bundle URL at the beginning of tests when working with Expo.
# Parameters
config
# appendField
Appends text into the field. A field can be located by text, accessibility id, id.
I.appendField('name', 'davert');
# Parameters
# checkIfElementExists
Checks if an element exists.
I.checkIfElementExists('~edit'); // located by accessibility id
I.checkIfElementExists('~edit', '#menu'); // element inside #menu
# Parameters
locator
(string (opens new window) | object (opens new window)) element to locatecontext
(string (opens new window) | object (opens new window) | null) context element (optional, defaultnull
)
# clearField
Clears a text field. A field can be located by text, accessibility id, id.
I.clearField('~name');
# Parameters
field
(string (opens new window) | object (opens new window)) an input element to clear
# click
Clicks on an element. Element can be located by its text or id or accessibility id
The second parameter is a context (id | type | accessibility id) to narrow the search.
Same as tap
I.click('Login'); // locate by text
I.click('~nav-1'); // locate by accessibility label
I.click('#user'); // locate by id
I.click('Login', '#nav'); // locate by text inside #nav
I.click({ ios: 'Save', android: 'SAVE' }, '#main'); // different texts on iOS and Android
# Parameters
locator
(string (opens new window) | object (opens new window))context
(string (opens new window) | object (opens new window) | null) (optional, defaultnull
)
# clickAtPoint
Performs click on element with horizontal and vertical offset. An element is located by text, id, accessibility id.
I.clickAtPoint('Save', 10, 10);
I.clickAtPoint('~save', 10, 10); // locate by accessibility id
# Parameters
locator
(string (opens new window) | object (opens new window))x
number (opens new window) horizontal offset (optional, default0
)y
number (opens new window) vertical offset (optional, default0
)
# dontSee
Checks text not to be visible. Use second parameter to narrow down the search.
I.dontSee('Record created');
I.dontSee('Record updated', '#message');
I.dontSee('Record deleted', '~message');
# Parameters
text
string (opens new window) to check invisibilitycontext
(string (opens new window) | object (opens new window) | null) element in which to search for text (optional, defaultnull
)
# dontSeeElement
Checks that element is not visible. Use second parameter to narrow down the search.
I.dontSeeElement('~edit'); // located by accessibility id
I.dontSeeElement('~edit', '#menu'); // element inside #menu
# Parameters
locator
(string (opens new window) | object (opens new window)) element to locatecontext
(string (opens new window) | object (opens new window) | null) context element (optional, defaultnull
)
# dontSeeElementExists
Checks that element not exists. Use second parameter to narrow down the search.
I.dontSeeElementExist('~edit'); // located by accessibility id
I.dontSeeElementExist('~edit', '#menu'); // element inside #menu
# Parameters
locator
(string (opens new window) | object (opens new window)) element to locatecontext
(string (opens new window) | object (opens new window)) context element (optional, defaultnull
)
# fillField
Fills in text field in an app. A field can be located by text, accessibility id, id.
I.fillField('Username', 'davert');
I.fillField('~name', 'davert');
I.fillField({ android: 'NAME', ios: 'name' }, 'davert');
# Parameters
field
(string (opens new window) | object (opens new window)) an input element to fill invalue
string (opens new window) value to fill
# goBack
Goes back on Android
I.goBack(); // on Android only
# grabPlatform
Grab the device platform
const platform = await I.grabPlatform();
# installApp
Installs a configured application. Application is installed by default.
I.installApp();
# launchApp
Launches an application. If application instance already exists, use relaunchApp.
I.launchApp();
# longPress
Taps an element and holds for a requested time.
I.longPress('Login', 2); // locate by text, hold for 2 seconds
I.longPress('~nav', 1); // locate by accessibility label, hold for second
I.longPress('Update', 2, '#menu'); // locate by text inside #menu, hold for 2 seconds
# Parameters
locator
(string (opens new window) | object (opens new window)) element to locatesec
number (opens new window) number of seconds to hold tapcontext
(string (opens new window) | object (opens new window) | null) context element (optional, defaultnull
)
# multiTap
Multi taps on an element. Element can be located by its text or id or accessibility id.
Set the number of taps in second argument. Optionally define the context element by third argument.
I.multiTap('Login', 2); // locate by text
I.multiTap('~nav', 2); // locate by accessibility label
I.multiTap('#user', 2); // locate by id
I.multiTap('Update', 2, '#menu'); // locate by id
# Parameters
locator
(string (opens new window) | object (opens new window)) element to locatenum
number (opens new window) number of tapscontext
(string (opens new window) | object (opens new window) | null) context element (optional, defaultnull
)
# relaunchApp
Relaunches an application.
I.relaunchApp();
# runOnAndroid
Execute code only on Android
I.runOnAndroid(() => {
I.click('Button');
I.see('Hi, Android');
});
# Parameters
fn
Function (opens new window) a function which will be executed on android
# runOnIOS
Execute code only on iOS
I.runOnIOS(() => {
I.click('Button');
I.see('Hi, IOS');
});
# Parameters
fn
Function (opens new window) a function which will be executed on iOS
# saveScreenshot
Saves a screenshot to the output dir
I.saveScreenshot('main-window.png');
# Parameters
# scrollDown
Scrolls to the bottom of an element.
I.scrollDown('#container');
# Parameters
locator
(string (opens new window) | object (opens new window))
# scrollLeft
Scrolls to the left of an element.
I.scrollLeft('#container');
# Parameters
locator
(string (opens new window) | object (opens new window))
# scrollRight
Scrolls to the right of an element.
I.scrollRight('#container');
# Parameters
locator
(string (opens new window) | object (opens new window))
# scrollToElement
Scrolls within a scrollable container to an element.
# Parameters
targetLocator
(string (opens new window) | object (opens new window)) Locator of the element to scroll tocontainerLocator
(string (opens new window) | object (opens new window)) Locator of the scrollable containerdirection
string (opens new window) 'up' or 'down' (optional, default'down'
)offset
number (opens new window) Offset for scroll, can be adjusted based on need (optional, default100
)
# scrollUp
Scrolls to the top of an element.
I.scrollUp('#container');
# Parameters
locator
(string (opens new window) | object (opens new window))
# see
Checks text to be visible. Use second parameter to narrow down the search.
I.see('Record created');
I.see('Record updated', '#message');
I.see('Record deleted', '~message');
# Parameters
text
string (opens new window) to check visibilitycontext
(string (opens new window) | object (opens new window) | null) element inside which to search for text (optional, defaultnull
)
# seeElement
Checks for visibility of an element. Use second parameter to narrow down the search.
I.seeElement('~edit'); // located by accessibility id
I.seeElement('~edit', '#menu'); // element inside #menu
# Parameters
locator
(string (opens new window) | object (opens new window)) element to locatecontext
(string (opens new window) | object (opens new window) | null) context element (optional, defaultnull
)
# seeElementExists
Checks for existence of an element. An element can be visible or not. Use second parameter to narrow down the search.
I.seeElementExists('~edit'); // located by accessibility id
I.seeElementExists('~edit', '#menu'); // element inside #menu
# Parameters
locator
(string (opens new window) | object (opens new window)) element to locatecontext
(string (opens new window) | object (opens new window)) context element (optional, defaultnull
)
# setLandscapeOrientation
Switches device to landscape orientation
I.setLandscapeOrientation();
# setPortraitOrientation
Switches device to portrait orientation
I.setPortraitOrientation();
# shakeDevice
Shakes the device.
I.shakeDevice();
# swipeDown
Performs a swipe up inside an element.
Can be slow
or fast
swipe.
I.swipeUp('#container');
# Parameters
locator
(string (opens new window) | object (opens new window)) an element on which to perform swipespeed
string (opens new window) a speed to perform:slow
orfast
. (optional, default'slow'
)
# swipeLeft
Performs a swipe up inside an element.
Can be slow
or fast
swipe.
I.swipeUp('#container');
# Parameters
locator
(string (opens new window) | object (opens new window)) an element on which to perform swipespeed
string (opens new window) a speed to perform:slow
orfast
. (optional, default'slow'
)
# swipeRight
Performs a swipe up inside an element.
Can be slow
or fast
swipe.
I.swipeUp('#container');
# Parameters
locator
(string (opens new window) | object (opens new window)) an element on which to perform swipespeed
string (opens new window) a speed to perform:slow
orfast
. (optional, default'slow'
)
# swipeUp
Performs a swipe up inside an element.
Can be slow
or fast
swipe.
I.swipeUp('#container');
# Parameters
locator
(string (opens new window) | object (opens new window)) an element on which to perform swipespeed
string (opens new window) a speed to perform:slow
orfast
. (optional, default'slow'
)
# tap
Taps on an element. Element can be located by its text or id or accessibility id.
The second parameter is a context element to narrow the search.
Same as click
I.tap('Login'); // locate by text
I.tap('~nav-1'); // locate by accessibility label
I.tap('#user'); // locate by id
I.tap('Login', '#nav'); // locate by text inside #nav
I.tap({ ios: 'Save', android: 'SAVE' }, '#main'); // different texts on iOS and Android
# Parameters
locator
(string (opens new window) | object (opens new window))context
(string (opens new window) | object (opens new window) | null) (optional, defaultnull
)
# tapByLabel
Clicks on an element. Element can be located by its label
The second parameter is a context (id | type | accessibility id) to narrow the search.
I.tapByLabel('Login'); // locate by text
I.tapByLabel('Login', '#nav'); // locate by text inside #nav
# Parameters
locator
(string (opens new window) | object (opens new window))context
(string (opens new window) | object (opens new window) | null) (optional, defaultnull
)
# tapReturnKey
Taps return key. A field can be located by text, accessibility id, id.
I.tapReturnKey('Username');
I.tapReturnKey('~name');
I.tapReturnKey({ android: 'NAME', ios: 'name' });
# Parameters
field
(string (opens new window) | object (opens new window)) an input element to fill in
# wait
Waits for number of seconds
I.wait(2); // waits for 2 seconds
# Parameters
sec
number (opens new window) number of seconds to wait
# waitForElement
Waits for an element to exist on page.
I.waitForElement('#message', 1); // wait for 1 second
# Parameters
locator
(string (opens new window) | object (opens new window)) an element to wait forsec
number (opens new window) number of seconds to wait, 5 by default (optional, default5
)
# waitForElementVisible
Waits for an element to be visible on page.
I.waitForElementVisible('#message', 1); // wait for 1 second
# Parameters
locator
(string (opens new window) | object (opens new window)) an element to wait forsec
number (opens new window) number of seconds to wait (optional, default5
)
# waitToHide
Waits an elmenet to become not visible.
I.waitToHide('#message', 2); // wait for 2 seconds
# Parameters
locator
(string (opens new window) | object (opens new window)) an element to wait forsec
number (opens new window) number of seconds to wait (optional, default5
)