Configuration
Mobilewright is configured through a mobilewright.config.ts file at the root of your project. Wrap the object in defineConfig for type-checking and editor autocomplete.
import { defineConfig } from 'mobilewright';
export default defineConfig({
platform: 'ios',
bundleId: 'com.example.myapp',
deviceName: /iPhone/,
timeout: 30_000,
});
Config file resolution
When you run mobilewright test, it looks for these files in the current directory, in order:
mobilewright.config.tsmobilewright.config.jsmobilewright.config.mjs
Pass --config <path> to point at a specific file instead. If no config is found, Mobilewright runs with defaults.
Device and app
Which device to run on and which app to drive.
| Option | Type | Default | Description |
|---|---|---|---|
platform | 'ios' | 'android' | — | Target platform |
deviceId | string | — | Specific device identifier (local drivers only) |
deviceName | RegExp | — | Match a device by name, e.g. /iPhone 17/ |
deviceType | 'simulator' | 'emulator' | 'real' | — | Restrict to simulators, emulators, or real devices |
osVersion | string | — | OS version constraint — see OS version constraints |
bundleId | string | — | App bundle ID to launch |
installApps | string | string[] | — | App paths (APK/IPA) to install before launching |
autoAppLaunch | boolean | true | Launch the app automatically after connecting |
OS version constraints
osVersion accepts a bare version or a comparator expression:
| Expression | Matches |
|---|---|
'17' | Any 17.x release (≥ 17, < 18) |
'26.0' | Exactly 26.0 (26.0.1 matches, 26.1 does not) |
'>=17' | 17 or newer |
'>=17 <19' | 17 or 18, not 19 |
A bare version is a prefix match. Comparator expressions combine at most one lower bound (>= or >) and one upper bound (< or <=), separated by a space.
export default defineConfig({
platform: 'ios',
deviceType: 'real',
osVersion: '>=17 <19',
});
Driver
The driver decides where tests run — a local device via mobilecli, or a cloud device. Pass an
instance constructed from a @mobilewright/driver-* package (or your own, implementing
MobilewrightDriver from @mobilewright/protocol). Each driver has its own constructor options —
there's no shared config shape to look up.
| Option | Type | Default | Description |
|---|---|---|---|
driver | MobilewrightDriver | new MobilecliDriver() | Driver instance to use (see below) |
Local (mobilecli):
import { MobilecliDriver } from '@mobilewright/driver-mobilecli';
// omit `driver` entirely to use these same defaults
driver: new MobilecliDriver({
url: 'ws://localhost:12000/ws', // mobilecli server URL (for a remote server)
autoStart: true, // auto-start the mobilecli server if it isn't running
mobilecliPath: undefined, // path to the mobilecli binary, if not on PATH
})
Cloud (Mobile Next):
import { MobileNextDriver } from '@mobilewright/driver-mobilenext';
driver: new MobileNextDriver({
apiKey: process.env.MOBILENEXT_API_KEY,
allocationTimeout: 300_000, // wait for a cloud device, ms (default: 5 min)
uploadTimeout: 60_000, // upload test results, ms (default: none)
})
Reporting
With the MobileNextDriver, test results are uploaded to mobilenext.ai automatically after
the run — no reporter configuration needed. Control it through the driver's testResult
option:
import { defineConfig } from 'mobilewright';
import { MobileNextDriver } from '@mobilewright/driver-mobilenext';
export default defineConfig({
driver: new MobileNextDriver({
apiKey: process.env.MOBILENEXT_API_KEY,
testResult: { uploadReport: 'on' }, // 'on' | 'off' | 'on-failure' (default: 'on')
uploadTimeout: 60_000, // ms, default: none
}),
});
Your own reporter: entries are preserved — Mobilewright appends what it needs alongside
them. If your config already includes a json reporter with an outputFile, that report is
reused for the upload instead of writing a second one.
Test runner
How tests are discovered and executed.
| Option | Type | Default | Description |
|---|---|---|---|
testDir | string | config file dir | Directory to search for tests |
testMatch | string | RegExp | Array | **/*.{test,spec}.{js,ts,mjs} | Glob patterns for test files |
testIgnore | string | RegExp | Array | — | Patterns to skip during discovery |
outputDir | string | test-results | Directory for test artifacts |
timeout | number | — | Per-test timeout in ms |
globalTimeout | number | — | Hard cap on the entire suite run in ms |
retries | number | — | Max retries for flaky tests — see Retries |
workers | number | string | 1 | Concurrent workers — see Parallelism |
fullyParallel | boolean | false | Run all tests in parallel |
forbidOnly | boolean | — | Fail the run if test.only is present (useful in CI) |
reporter | 'list' | 'html' | 'json' | 'junit' | Array | — | Reporter(s) to use |
globalSetup | string | string[] | — | File(s) run once before all tests |
globalTeardown | string | string[] | — | File(s) run once after all tests |
projects | ProjectConfig[] | — | Multi-device / multi-platform matrix — see Projects |
Timeouts and per-action defaults
use sets defaults applied to every test. expect sets the default assertion timeout. Both can be overridden per project and per call.
export default defineConfig({
use: {
actionTimeout: 5_000, // tap, fill, etc. — default 5000
appLaunchTimeout: 20_000, // wait for app foreground — default 20000
installTimeout: 120_000, // installApps — default none
animations: 'off', // system animations: 'on' | 'off'
},
expect: {
timeout: 5_000, // toBeVisible, toHaveText, etc. — default 5000
},
});
See Timeouts for how these interact and how to override them at call sites.
Report metadata
| Option | Type | Default | Description |
|---|---|---|---|
viewTree | 'on-failure' | 'off' | 'off' | Attach the accessibility tree as JSON to the report; 'on-failure' attaches only on failing tests |
captureGitInfo | { commit?: boolean; diff?: boolean } | — | Capture git commit info into report metadata |
Per-project overrides
Everything that varies by device belongs in projects. Each project has a use block that overrides the top-level settings for that run.
export default defineConfig({
bundleId: 'com.example.myapp',
projects: [
{ name: 'iOS', use: { platform: 'ios', deviceName: /iPhone/ } },
{ name: 'Android', use: { platform: 'android', deviceName: /Pixel/ } },
],
});
The project use block accepts platform, deviceId, deviceName, deviceType, osVersion, bundleId, installApps, animations, actionTimeout, appLaunchTimeout, and installTimeout. Projects can also override timeout, testDir, testMatch, testIgnore, outputDir, retries, grep, grepInvert, and declare dependencies on other projects. See Projects for the full matrix.