Detox end-to-end tests can need a longer Jest timeout than small unit tests because each test drives a simulator or emulator while the app renders, synchronizes, and returns assertions. Setting the timeout at the runner layer prevents a legitimate mobile flow from failing before the app has enough time to finish.
Detox 20.x runs on top of a configured test runner, and the standard project setup uses Jest. The shared e2e/jest.config.js value testTimeout sets the default per-test budget for the Detox suite, while testRunner.args.testTimeout in .detoxrc.js can pass the same Jest option from the Detox config.
A larger test timeout should match a real long-running mobile flow, not hide a synchronization problem. If Detox reports busy resources, pending animations, or network work, debug that wait separately before raising the timeout for the whole suite.
Related: How to run Detox tests locally
Related: How to debug Detox synchronization timeouts
Related: How to retry failed Detox tests
Steps to set Detox test timeouts:
- Confirm the timeout message belongs to the test body.
$ npx detox test --configuration ios.sim.debug e2e/checkout-timeout.test.js FAIL e2e/checkout-timeout.test.js Checkout x shows the receipt after polling (120003 ms) thrown: "Exceeded timeout of 120000 ms for a test. Add a timeout value to this test to increase the timeout, if this is a long-running test."If the message says while setting up Detox environment, use testRunner.jest.setupTimeout instead of the Jest test timeout. If Detox prints busy resources or pending animations, debug synchronization first.
Related: How to debug Detox synchronization timeouts - Open the Jest config used by the Detox suite.
$ vi e2e/jest.config.js
detox init creates e2e/jest.config.js for the standard Jest integration. Use the config file named by testRunner.args.config when the project stores the runner config somewhere else.
- Set the shared Jest test timeout for the Detox suite.
- e2e/jest.config.js
/** @type {import('@jest/types').Config.InitialOptions} */ module.exports = { rootDir: '..', testMatch: ['<rootDir>/e2e/**/*.test.js'], testTimeout: 180000, maxWorkers: 1, globalSetup: 'detox/runners/jest/globalSetup', globalTeardown: 'detox/runners/jest/globalTeardown', reporters: ['detox/runners/jest/reporter'], testEnvironment: 'detox/runners/jest/testEnvironment', verbose: true, };
Detox starter projects use 120000 milliseconds for this value. Raise it only to the smallest value that covers the expected mobile flow.
- Use a Detox runner argument when the timeout should be owned by .detoxrc.js.
- .detoxrc.js
/** @type {Detox.DetoxConfig} */ module.exports = { testRunner: { args: { $0: 'jest', config: 'e2e/jest.config.js', testTimeout: 180000, _: ['e2e'], }, }, apps: { // existing app definitions }, devices: { // existing device definitions }, configurations: { // existing Detox configurations }, };
testRunner.args.testTimeout is translated into --testTimeout 180000 for the underlying Jest command. Keep the timeout in one place unless the project deliberately varies it by Detox configuration.
- Set Detox setup or teardown timeouts only when the failure names that phase.
- .detoxrc.js
/** @type {Detox.DetoxConfig} */ module.exports = { testRunner: { jest: { setupTimeout: 180000, teardownTimeout: 60000, }, }, apps: { // existing app definitions }, devices: { // existing device definitions }, configurations: { // existing Detox configurations }, };
setupTimeout covers device boot, app install, and Detox environment setup before the suite starts. teardownTimeout covers the environment shutdown after the suite finishes.
- Verify the resolved Jest config shows the new timeout.
$ npx jest --config e2e/jest.config.js --showConfig { "configs": [ { "globalSetup": "detox/runners/jest/globalSetup", "globalTeardown": "detox/runners/jest/globalTeardown", "testEnvironment": "detox/runners/jest/testEnvironment", "testMatch": [ "/Users/example/app/e2e/**/*.test.js" ], "testTimeout": 180000, "verbose": true } ], "globalConfig": { "testTimeout": 180000 } } ##### snipped ##### - Run the focused Detox spec again.
$ npx detox test --configuration ios.sim.debug e2e/checkout-timeout.test.js detox[run_tests] ios.sim.debug PASS e2e/checkout-timeout.test.js Checkout PASS shows the receipt after polling (134.7 s) Test Suites: 1 passed, 1 total Tests: 1 passed, 1 totalIf the failure changes to a missing matcher, app error, busy resource, or network wait, the timeout setting is no longer the main blocker. Keep the timeout value and debug the new signal from logs or artifacts.
Related: How to run Detox tests locally
Related: How to debug Detox synchronization timeouts
Mohd Shakir Zakaria is a cloud architect with deep roots in software development and open-source advocacy. Certified in AWS, Red Hat, VMware, ITIL, and Linux, he specializes in designing and managing robust cloud and on-premises infrastructures.