Skip to content

What is Argus

Argus runs React Native unit tests on the standalone Hermes VM — the same JavaScript engine your app ships with — without starting Metro, building a native app, or booting a device or emulator.

The goal is narrow and deliberate: keep the feedback loop at unit-test speed while catching the bugs that only appear on Hermes and are invisible to a Node/V8 runner.

Each test file is bundled by esbuild into a sealed IIFE, written to a temp file, and run by a freshly spawned hermes process. The process prints one framed result line; the host parses it, remaps the stacks, and reports.

argus "src/**/*.test.ts"
→ discover files
→ for each file (bounded parallelism):
bundle → spawn hermes → parse framed result → remap stacks
→ aggregate → report → exit with the worst-case code

One process per file. No shared realm between files, no cross-test global leakage, and parallelism that is just process parallelism.

Option Strength Gap
Jest / Vitest on Node Fast, familiar, great DX Wrong JS engine for RN production
On-device / emulator runners Real app environment Slow, heavy, needs a native build
Argus Real Hermes VM at unit-test cost Not a full RN runtime

Argus is not trying to be another Jest. It implements a Jest-shaped surface where that buys ergonomics, and stops where the shape would start lying about the engine.

  • Multi-file discovery with globs, and bounded parallel execution.
  • describe, test, it, expect, the four lifecycle hooks.
  • .skip, .only, .todo.
  • Async tests and async matchers through Hermes microtasks.
  • A full matcher set: equality, truthiness, numeric, string, collection, object, toThrow, .resolves / .rejects, call and return matchers, expect.extend, assertion counting.
  • argus.fn(), argus.spyOn(), and React Native native-module mocks.
  • Source-map based stack remapping back to your original TypeScript.
  • Synchronous component testing on real React 19 inside Hermes.
  • Hermes provisioning driven by the engine your project pins.

Argus is not a React Native runtime. It does not give you Metro semantics, native app lifecycle, device APIs, real UI rendering, or layout. See Limitations & non-goals — those boundaries are chosen, not pending.