| name | Detox Mobile Testing |
| description | Gray-box end-to-end testing for React Native apps with Detox. Covers .detoxrc.js configuration, build and test commands, matchers, device.launchApp control, automatic synchronization, and macOS CI pipelines. |
| version | 1.0.0 |
| author | thetestingacademy |
| license | MIT |
| tags | ["detox","react-native","mobile","e2e","ios","android","simulator","emulator","gray-box"] |
| testingTypes | ["mobile","e2e"] |
| frameworks | ["appium","jest"] |
| languages | ["javascript","typescript"] |
| domains | ["mobile"] |
| agents | ["claude-code","cursor","github-copilot","windsurf","codex","aider","continue","cline","zed","bolt","gemini-cli","amp"] |
Detox Mobile Testing
This skill makes an AI agent write and run Detox gray-box E2E tests for React Native apps: configure .detoxrc.js for iOS simulators and Android emulators, build test binaries, write tests with element(by.id(...)) matchers, control the app lifecycle with device.launchApp, and lean on Detox's automatic synchronization instead of sleeps. Trigger it in React Native repositories containing an e2e/ directory, detox in package.json, or when the user asks for end-to-end tests on iOS/Android simulators.
Core Principles
- Detox is gray-box: it waits for the app to be idle. Detox monitors the JS event loop, network requests, timers, and animations, and only acts when the app is quiescent. Trust this; almost every
sleep() in a Detox suite is a bug.
- Match by
testID, never by text or traversal. Text changes with copy edits and localization; view hierarchy changes with refactors. Add testID="login-button" props in the app code as part of writing the test.
- Test release builds. Dev builds bundle the dev menu, yellow boxes, and a Metro dependency that makes timing unrealistic. CI must run
assembleRelease / -configuration Release binaries.
- Each test starts from a known app state. Use
device.launchApp({ newInstance: true }) or device.reloadReactNative() in beforeEach; tests that depend on the previous test's screen are unmaintainable.
- Handle permissions at launch, not with dialog-clicking.
device.launchApp({ permissions: { notifications: 'YES', location: 'inuse' } }) sets iOS permissions deterministically; tapping system dialogs is flaky and Detox cannot see them anyway.
- Disable synchronization only as a last resort, and re-enable immediately. Endless animations (spinners, maps, video) can keep the app permanently busy; scope
device.disableSynchronization() to the smallest possible window.
Setup
npm install --save-dev detox jest @types/jest
brew tap wix/brew
brew install applesimutils
npx detox init
.detoxrc.js
. = {
: {
: {
: ,
: [],
},
: { : },
},
: {
: {
: ,
: ,
:
,
},
: {
: ,
: ,
:
,
},
},
: {
: { : , : { : } },
: { : , : { : } },
},
: {
: { : , : },
: { : , : },
},
};