Quick Start

React Native Harness allows you to write Jest-style tests that run directly in your React Native app with full access to native modules. Let's get you set up in minutes.

Installation

Install React Native Harness as a development dependency:

npm
yarn
pnpm
bun
npm install react-native-harness

Configuration

1. Create Harness Configuration

Create a rn-harness.config.mjs file in your project root:

const config = {
  include: ['./src/**/*.harness.{js,ts,jsx,tsx}'],

  runners: [
    {
      name: 'android',
      platform: 'android',
      deviceId: 'Pixel_8_API_35', // Your Android emulator name
      bundleId: 'com.yourapp', // Your Android bundle ID
    },
    {
      name: 'ios',
      platform: 'ios',
      deviceId: 'iPhone 16 Pro', // Your iOS simulator name
      bundleId: 'com.yourapp', // Your iOS bundle ID
      systemVersion: '18.0',
    },
  ],
};

export default config;

For detailed information about all configuration options, see the Configuration page.

2. Update Metro Configuration

Update your metro.config.js so React Native Harness will be able to use it to bundle its tests:

const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config');
const { withRnHarness } = require('react-native-harness/metro');

const defaultConfig = getDefaultConfig(__dirname);

const customConfig = {
  // Your existing Metro config
};

module.exports = withRnHarness(mergeConfig(defaultConfig, customConfig));

3. Update Babel Configuration

Add the required preset to babel.config.js. This is needed for module mocking and bundling speedup when running tests.

module.exports = {
  presets: ['module:@react-native/babel-preset', 'react-native-harness/babel'],
  // Your existing Babel config
};

4. Update Your Entry Point

Add a conditional entry point to your index.js or main entry file. This allows React Native Harness to take over the app when needed and run tests.

// index.js (or your main entry file)
import { AppRegistry } from 'react-native';

AppRegistry.registerComponent(
  'YourAppName',
  () =>
    global.RN_HARNESS
      ? require('react-native-harness').ReactNativeHarness
      : require('./App').default // Your normal app component
);

5. TypeScript Support (Optional)

If you're using TypeScript, add a react-native-harness.d.ts file to your project root to get proper type definitions:

/// <reference types="react-native-harness/types" />

This way, your app will know about the RN_HARNESS global and won't mark it as an error.

Writing Your First Test

Create a test file with a .harness.js or .harness.ts extension. Import testing utilities from react-native-harness instead of Jest:

// MyComponent.harness.js
import {
  describe,
  it,
  expect,
  beforeEach,
  afterEach,
} from 'react-native-harness';
import { NativeModules, Platform } from 'react-native';

describe('My First Harness Test', () => {
  beforeEach(() => {
    console.log('Setting up test...');
  });

  afterEach(() => {
    console.log('Cleaning up test...');
  });

  it('should access platform information', () => {
    expect(Platform.OS).toMatch(/ios|android/);
    expect(typeof Platform.Version).toBe('string');
  });

  it('should have access to native modules', () => {
    // Test real native modules - no mocks!
    expect(NativeModules).toBeDefined();
    expect(typeof NativeModules).toBe('object');
  });

  it('should run async tests', async () => {
    const result = await Promise.resolve('native testing');
    expect(result).toBe('native testing');
  });
});

Available Testing APIs

React Native Harness provides Jest-compatible APIs through react-native-harness:

Test Structure

  • describe(name, fn) - Group related tests
  • it(name, fn) or test(name, fn) - Define individual tests
  • it.skip() or test.skip() - Skip tests
  • it.only() or test.only() - Run only specific tests

Lifecycle Hooks

  • beforeAll(fn) - Run once before all tests
  • afterAll(fn) - Run once after all tests
  • beforeEach(fn) - Run before each test
  • afterEach(fn) - Run after each test

Assertions

Create expectations using expect(value) with matchers:

  • .toBe() - Strict equality
  • .toEqual() - Deep equality
  • .toBeTruthy() - Truthy values
  • .toBeFalsy() - Falsy values
  • .toContain() - Array/string contains
  • .toHaveLength() - Length check
  • .toMatch() - Regex match
  • .toBeInstanceOf() - Instance type
  • .toHaveProperty() - Object property

...and many more Jest-compatible matchers.

Building Your App

Before running tests, you need to build your app in debug mode and install it on your emulator or simulator. React Native Harness will inject itself into your existing app, taking over access to all included native modules.

Follow your framework's documentation to build and install the debug variant:

React Native Community CLI

npm
yarn
pnpm
bun
npm react-native run-android
npm
yarn
pnpm
bun
npm react-native run-ios

Expo

npm
yarn
pnpm
bun
npm expo run:android
npm
yarn
pnpm
bun
npm expo run:ios

Rock

npm
yarn
pnpm
bun
npm rock run:android
npm
yarn
pnpm
bun
npm rock run:ios

Running Tests

Use the React Native Harness CLI to run your tests:

npm
yarn
pnpm
bun
npm react-native-harness test android
npm
yarn
pnpm
bun
npm react-native-harness test ios

What's Next?

Congratulations! You now have React Native Harness set up and can write tests that run in real native environments.

Need React or React Native expertise you can count on?

Need to boost your app's performance?
We help React Native teams enhance speed, responsiveness, and efficiency.