Real Hermes, not an emulation
The hermes CLI VM, spawned as a subprocess per file. Same bytecode model React
Native uses on device — compile to HBC, interpret it.
Argus bundles each test file into a sealed IIFE, spawns the standalone hermes VM on it,
and reads a framed result line back. No Metro, no native build, no emulator — and no V8
pretending to be Hermes.
// src/sum.ts — the code under test. Argus bundles your imports, so it has to exist.export function sum(a: number, b: number): number { if (typeof a !== 'number' || typeof b !== 'number') throw new TypeError('numbers only'); return a + b;}// src/sum.test.ts — plain TypeScript, running on the real Hermes VMimport { sum } from './sum';
describe('sum', () => { test('adds numbers', () => { expect(sum(2, 3)).toBe(5); });
test('rejects a non-number', () => { expect(() => sum(2, 'three' as never)).toThrow(TypeError); });});npm install --save-dev @arguslab/argusnpx argus "src/**/*.test.ts"One package, one binary. React is an optional peer — a pure-TypeScript suite runs without it.
Real Hermes, not an emulation
The hermes CLI VM, spawned as a subprocess per file. Same bytecode model React
Native uses on device — compile to HBC, interpret it.
Jest-shaped surface
describe / test / it, the four hooks, .skip / .only / .todo, async tests,
expect.extend, assertion counting. Familiar where familiarity helps.
Engine pinned by your project
Argus reads the Hermes version your React Native install pins, then provisions exactly that VM. Legacy and V1 both supported.
Stacks that point at your source
Failure stacks are remapped through the bundle’s source map, back to the original
.ts / .tsx line you wrote.
Component testing on real React
render, screen, getBy*, findBy*, waitFor, fireEvent, act — real React 19 running
inside Hermes, not a DOM shim on Node.
A hardened result channel
User tests can pollute prototypes and hijack globals. The result frame survives it: captured primordials, a private nonce, a hand-written serializer.