Skip to content

A runner for node:test, jest, and tape test suites on top of node:test (and any runtime)

License

Notifications You must be signed in to change notification settings

ExodusMovement/test

Repository files navigation

@exodus/test

A runner for node:test, jest, and tape test suites on top of node:test (and any runtime)

Features

  • Native ESM, including in Jest tests
  • Esbuild on the fly for babelified ESM interop (enable via --esbuild)
  • TypeScript support in both transform (through tsx, enable via --esbuild) and typestrip (via --typescript) modes
  • Runs on node:test, and (experimental) on bun, deno, d8, JSC and Hermes
  • Testsuite-agnostic -- can run any file as long as it sets exit code based on test results
  • Built-in Jest compatibility (with --jest), including jest.* global
    • Up to ~10x faster depending on the original setup
    • Actual expect module, also jest-extended and jest-when just work on top
    • Snapshots, including snapshot matchers
    • Function and timer mocks
    • test.concurrent
    • Module mocks (on top of Node.js runtime only), including for ESM modules
    • Loads Jest configuration
    • It works on Hermes too!
  • Built-in network record/replay for offline tests, mocking fetch and WebSocket sessions
  • --drop-network support for guaranteed offline testing
  • Native code coverage via v8 (Node.js or c8), with istanbul reporters
  • GitHub reporter (auto-enabled by default)
  • JSDOM env support
  • Hanging tests error by default (unlike jest)
  • Babel support, picks up your Babel config (enable via --babel)
  • Unlike bun:test, it runs test files in isolated contexts
    Bun leaks globals / side effects between test files (ref), and has incompatible test() lifecycle / order
  • Also features a tape API for drop-in replacement

Reporter samples

CLI (but uses colors when output supports them, e.g. in terminal):

# tests/jest/expect.mock.test.js
✔ PASS drinkAll > drinks something lemon-flavoured (1.300417ms)
✔ PASS drinkAll > does not drink something octopus-flavoured (0.191791ms)
✔ PASS drinkAll (1.842959ms)
✔ PASS drinkEach > drinkEach drinks each drink (0.360625ms)
✔ PASS drinkEach (0.463416ms)
✔ PASS toHaveBeenCalledWith > registration applies correctly to orange La Croix (0.53325ms)
✔ PASS toHaveBeenCalledWith (0.564166ms)
✔ PASS toHaveBeenLastCalledWith > applying to all flavors does mango last (0.380375ms)
✔ PASS toHaveBeenLastCalledWith (0.473417ms)
# tests/jest/fn.invocationCallOrder.test.js
✔ PASS mock.invocationCallOrder (4.221042ms)

GitHub Actions collapses test results per-file, like this:

tests/jest/lifecycle.test.js
  ✔ PASS A > B > C (3.26166ms)
  ✔ PASS A > B > D (1.699463ms)
  ✔ PASS A > B (6.72719ms)
  ✔ PASS A > E > F (1.117997ms)
  ✔ PASS A > E > G > H (1.330904ms)
  ✔ PASS A > E > G (1.94971ms)
  ✔ PASS A > E (3.821825ms)
  ✔ PASS A > I (0.533096ms)
  ✔ PASS A (13.887889ms)
  ✔ PASS J (0.373187ms)
  ✔ PASS K > L (0.659852ms)
  ✔ PASS K (1.143195ms)
 
tests/jest/timers.async.test.js
  ✔ PASS advanceTimersByTime() does not let microtasks to pass (5.326604ms)
  ✔ PASS advanceTimersByTime() does not let microtasks to pass even with await (1.336064ms)
  ✔ PASS advanceTimersByTimeAsync() lets microtasks to pass (6.99526ms)
  ✔ PASS advanceTimersByTimeAsync() lets microtasks to pass, chained (10.131664ms)
  ✔ PASS advanceTimersByTimeAsync() lets microtasks to pass, longer chained (8.635472ms)
  ✔ PASS advanceTimersByTimeAsync() lets microtasks to pass, async chain (56.937983ms)
 

See live output in CI

Library

List of exports

  • @exodus/test/node -- node:test API, working under non-Node.js platforms

  • @exodus/test/jest -- jest implementation

  • @exodus/test/tape -- tape mock (can also be helpful when moving from tap)

Binary

Just use "test": "exodus-test"

Options

  • --jest -- register jest test helpers as global variables, also load jest.config.* configuration options

  • --esbuild -- use esbuild loader, also enables Typescript support

  • --babel -- use babel loader (slower than --esbuild, makes sense if you have a special config)

  • --coverage -- enable coverage, prints coverage output (varies by coverage engine)

  • --coverage-engine c8 -- use c8 coverage engine (default), also generates ./coverage/ dirs

  • --coverage-engine node -- use Node.js builtint coverage engine

  • --watch -- operate in watch mode and re-run tests on file changes

  • --only -- only run the tests marked with test.only

  • --passWithNoTests -- do not error when no test files were found

  • --write-snapshots -- write snapshots instead of verifying them (has --test-update-snapshots alias)

  • --test-force-exit -- force exit after tests are done (useful in integration tests where it could be unfeasible to resolve all open handles)

License

MIT

About

A runner for node:test, jest, and tape test suites on top of node:test (and any runtime)

Resources

License

Stars

Watchers

Forks