Configuration
React Native Harness can be configured through a configuration object that defines various aspects of your testing setup.
The most basic configuration would, assuming you support both iOS and Android platforms, look like this:
rn-harness.config.mjs
import {
androidPlatform,
androidEmulator,
} from '@react-native-harness/platform-android';
import {
applePlatform,
appleSimulator,
} from '@react-native-harness/platform-apple';
const config = {
entryPoint: './index.js',
appRegistryComponentName: 'App',
runners: [
androidPlatform({
name: 'android',
device: androidEmulator('Pixel_8_API_35'),
bundleId: 'com.yourapp',
}),
applePlatform({
name: 'ios',
device: appleSimulator('iPhone 16 Pro', '18.0'),
bundleId: 'com.yourapp',
}),
],
};
export default config;
Entry Point and App Component
React Native Harness needs to know how to locate and integrate with your React Native app.
entryPoint
The path to your React Native app's entry point file.
{
entryPoint: './src/main.tsx',
}
appRegistryComponentName
The name of the component registered with React Native's AppRegistry.
// In your app's entry point
import { AppRegistry } from 'react-native';
import App from './App';
AppRegistry.registerComponent('MyApp', () => App);
// In your rn-harness.config.mjs
{
appRegistryComponentName: 'MyApp',
}
Expo
For Expo projects, the entryPoint should be set to the path specified in the main property of package.json. The appRegistryComponentName is typically set to main for Expo apps.
All Configuration Options
{
// Required: Entry point file for your React Native app
entryPoint: string;
// Required: Name of the component registered with AppRegistry
appRegistryComponentName: string;
// Required: Array of test runners (at least one required)
runners: Array<TestRunnerConfig>;
// Optional: Default runner to use when none specified
defaultRunner?: string;
// Optional: Bridge timeout in milliseconds (default: 60000)
bridgeTimeout?: number;
// Optional: Bundle start timeout in milliseconds (default: 15000)
bundleStartTimeout?: number;
// Optional: Maximum number of app restarts when app fails to report ready (default: 2)
maxAppRestarts?: number;
// Optional: Reset environment between test files (default: true)
resetEnvironmentBetweenTestFiles?: boolean;
}
Test Runners
A test runner defines how tests are executed on a specific platform. React Native Harness uses platform-specific packages to create runners with type-safe configurations.
Android Runner
Install the Android platform package:
npm install @react-native-harness/platform-android
Usage:
import {
androidPlatform,
androidEmulator,
physicalAndroidDevice,
} from '@react-native-harness/platform-android';
// Emulator configuration
androidPlatform({
name: 'android-emulator',
device: androidEmulator('Pixel_8_API_35'),
bundleId: 'com.myapp.debug',
});
// Physical device configuration
androidPlatform({
name: 'android-device',
device: physicalAndroidDevice('Motorola', 'Moto G72'),
bundleId: 'com.myapp.debug',
});
Apple (iOS) Runner
Install the Apple platform package:
npm install @react-native-harness/platform-apple
Usage:
import {
applePlatform,
appleSimulator,
applePhysicalDevice,
} from '@react-native-harness/platform-apple';
// Simulator configuration
applePlatform({
name: 'ios-simulator',
device: appleSimulator('iPhone 16 Pro', '18.0'),
bundleId: 'com.myapp',
});
// Physical device configuration
applePlatform({
name: 'ios-device',
device: applePhysicalDevice('iPhone (Your Name)'),
bundleId: 'com.myapp',
});
Vega Runner
Install the Vega platform package:
npm install @react-native-harness/platform-vega
Usage:
import {
vegaPlatform,
vegaEmulator,
} from '@react-native-harness/platform-vega';
vegaPlatform({
name: 'vega',
device: vegaEmulator('VegaTV_1'),
bundleId: 'com.myapp',
});
Default Runner
When you have multiple runners configured, you can specify which one to use by default when no runner is explicitly specified in the CLI command.
import {
androidPlatform,
androidEmulator,
} from '@react-native-harness/platform-android';
import {
applePlatform,
appleSimulator,
} from '@react-native-harness/platform-apple';
const config = {
runners: [
androidPlatform({
name: 'android',
device: androidEmulator('Pixel_8_API_35'),
bundleId: 'com.myapp',
}),
applePlatform({
name: 'ios',
device: appleSimulator('iPhone 16 Pro', '18.0'),
bundleId: 'com.myapp',
}),
],
defaultRunner: 'android', // Will use Android runner by default
};
If no defaultRunner is specified, you must explicitly provide the --harnessRunner flag when running tests:
# With default runner set (uses the runner specified in defaultRunner)
react-native-harness
# Without default runner (explicit runner required)
react-native-harness --harnessRunner android
react-native-harness --harnessRunner ios
Bridge Timeout
The bridge timeout controls how long React Native Harness waits for communication between the test runner and the React Native app. This is particularly important for slower devices or complex test setups.
{
bridgeTimeout: 120000, // 2 minutes in milliseconds
}
Default: 60000 (60 seconds)
Minimum: 1000 (1 second)
Increase this value if you experience timeout errors, especially on:
- Slower devices or simulators
- Complex test suites with heavy setup
Bundle Start Timeout
The bundle start timeout controls how long React Native Harness waits for Metro to start bundling after the app is restarted. This timeout is used in conjunction with the app restart mechanism to detect when an app has failed to report ready.
{
bundleStartTimeout: 30000, // 30 seconds in milliseconds
}
Default: 15000 (15 seconds)
Minimum: 1000 (1 second)
This timeout works with the maxAppRestarts setting to automatically restart the app when it fails to communicate with the test harness. If no bundling activity is detected within this timeout period, the app will be restarted automatically.
Maximum App Restarts
The maximum app restarts setting controls how many times React Native Harness will attempt to restart the app when it fails to report ready within the configured timeout periods.
{
maxAppRestarts: 3, // Allow up to 3 restart attempts
}
Default: 2
Minimum: 0
When set to 0, automatic app restarting is disabled. Higher values provide more resilience against flaky test environments but may increase test execution time. The app will be restarted when:
- No bundling activity is detected within the
bundleStartTimeout period
- The bridge fails to establish communication within the
bridgeTimeout period
Environment-Specific Configurations
You can create different configurations for different environments:
rn-harness.config.mjs
import {
androidPlatform,
androidEmulator,
} from '@react-native-harness/platform-android';
const isDevelopment = process.env.NODE_ENV === 'development';
const isCI = process.env.CI === 'true';
const config = {
runners: isDevelopment
? [
// Development runners with local simulators
androidPlatform({
name: 'android',
device: androidEmulator('Pixel_8_API_35'),
bundleId: 'com.myapp.debug',
}),
]
: [
// CI runners with headless or cloud devices
androidPlatform({
name: 'android',
device: androidEmulator('emulator-5554'),
bundleId: 'com.myapp.debug',
}),
],
bridgeTimeout: isCI ? 180000 : 60000, // Longer timeout in CI
};
export default config;
Finding Device and Simulator IDs
Android Emulators
List available Android emulators:
iOS Simulators
List available iOS simulators:
xcrun simctl list devices
The device ID is the name shown in the simulator list (e.g., "iPhone 16 Pro", "iPad Air").
System Version Required
React Native Harness requires the iOS version to be specified when using appleSimulator() because there can be multiple simulators with the same device name but different iOS versions (e.g., "iPhone 16 Pro" with iOS 17.0 and "iPhone 16 Pro" with iOS 18.0). The system version ensures Harness targets the correct simulator.

Need React or React Native
expertise you can count on?