Skip to content

Quick start

  1. Install the runner. One package, one binary.

    Terminal window
    pnpm add -D @arguslab/argus

    For type-checking, point TypeScript at the shipped declarations — it does not find them on its own. See Installation → TypeScript.

    tsconfig.json
    { "compilerOptions": { "types": ["@arguslab/argus"] } }
  2. Write something to test. Argus bundles your test and its imports, so the module under test has to exist — an unresolved import is a bundle failure, not a red test.

    src/money.ts
    export function formatCents(cents: number): string {
    if (cents < 0) throw new RangeError('amount must not be negative');
    return (Math.round(cents) / 100).toFixed(2);
    }
  3. Write a test. No import of the test API is needed — describe, test, it, expect and the hooks are installed as globals inside the Hermes realm.

    src/money.test.ts
    import { formatCents } from './money';
    describe('formatCents', () => {
    test('formats whole euros', () => {
    expect(formatCents(1200)).toBe('12.00');
    });
    test('rounds half up', () => {
    expect(formatCents(1205)).toBe('12.05');
    });
    test('rejects a negative amount', () => {
    expect(() => formatCents(-1)).toThrow(RangeError);
    });
    });
  4. Run it.

    Terminal window
    pnpm exec argus "src/**/*.test.ts"
    ✓ hermes v1 hermes-v250829098.0.16 · prebuilt darwin-arm64 · ~/.argus/cache/…/bin/hermes
    formatCents
    ✓ formats whole euros
    ✓ rounds half up
    ✓ rejects a negative amount
    3 passed, 0 failed, 0 todo, 3 total (0 ms in Hermes)
    ✓ money.test.ts
    1 files: 1 passed, 0 failed
    3 tests: 3 passed, 0 failed, 0 todo

    That first line is the prebuilt path, which applies on React Native 0.86 and 0.87. On other versions Argus names a different source — see How the binary is provisioned.

  5. Break it on purpose, so you can see what a failure looks like.

    test('rounds half up', () => {
    expect(formatCents(1205)).toBe('12.06'); // wrong
    });
    formatCents
    ✓ formats whole euros
    ✗ rounds half up — expect("12.05").toBe("12.06")
    Error: expect("12.05").toBe("12.06")
    at toBe (…/argus-MCNniB/run.argus-bundle.js:1105:24)
    at apply (native)
    at counted (…/argus-MCNniB/run.argus-bundle.js:437:26)
    at anonymous (src/money.test.ts:9:31)
    …
    ✓ rejects a negative amount
    2 passed, 1 failed, 0 todo, 3 total (0 ms in Hermes)
    ✗ money.test.ts (1 of 3 failed)
    1 files: 0 passed, 1 failed
    3 tests: 2 passed, 1 failed, 0 todo

    One frame in that stack is yours — src/money.test.ts:9:31, the line you just broke, not run.argus-bundle.js:1105. Frames inside the bundle stay as bundle frames on purpose: they are Argus’ own, and pretending they map to your source would be a lie. See Source maps.

  6. Add it to package.json so it runs like any other check.

    package.json
    {
    "scripts": {
    "test:hermes": "argus \"src/**/*.test.ts\" \"src/**/*.test.tsx\""
    }
    }

    Or move the globs into an optional argus.config.ts and leave the script as plain argus — see Configuration.

For that one file, Argus:

  1. Read node_modules/react-native to find which Hermes engine and version your project pins.
  2. Resolved a binary for it — cache, then the published prebuilt, verifying its checksum.
  3. Bundled the test and its imports into a single sealed IIFE, lowered to the Hermes syntax envelope, with an external source map.
  4. Spawned hermes on that file, in its own process.
  5. Read back exactly one framed result line carrying a private per-run nonce.
  6. Remapped every stack frame to your source, and rendered the report.