clearlydefined / clearlydefined/service
Evaluate migrating from mocha/chai/sinon to the Node.js test runner
- Dominant language
- TypeScript
- Stars
- 51
- Forks
- 46
- PR merge metrics
- No merged PRs in 30d
Description
We're running mocha + chai + sinon + nyc + proxyquire across 67 test files. That's five test dependencies (plus their `@types/*` packages) for functionality that Node.js now ships out of the box.
The Node test runner (`node:test`) in Node 24 has `describe`/`it`/`beforeEach`, built-in mocking via `mock.fn()`/`mock.method()`, fake timers via `mock.timers`, code coverage via `--experimental-test-coverage`, and snapshot testing. It also auto-discovers `.ts` test files when type stripping is on.
Worth looking into, but there are real tradeoffs.
## What we'd gain
- **No test framework dependencies.** mocha, chai, sinon, nyc, proxyquire, chai-as-promised, deep-equal-in-any-order (and their @types) all go away.
- **`mock.module()` does ESM module mocking.** This is the one thing our current stack can't do. proxyquire is CJS-only and sinon can't stub ES module exports. `mock.module()` mocks CJS, ESM, JSON imports, and builtins. That said, it needs `--experimental-test-module-mocks` and is Stability 1.0.
- **Native .ts file discovery.** `node --test` finds `test/**/*.ts` files automatically when type stripping is enabled. No mocha glob config needed.
- **Built-in coverage.** Replaces nyc, though the output is less mature.
- **Watch mode, test sharding, snapshot tests** come free.
## What we'd lose (or have to work around)
- **Assertion expressiveness.** chai's `expect(x).to.be.deep.equal(y)` and chaining becomes `assert.deepStrictEqual(x, y)`. Functional but less readable for complex assertions. No built-in equivalent to deep-equal-in-any-order.
- **Stub/spy richness.** sinon gives us `.resolves()`, `.calledOnceWith()`, `.onFirstCall()`, `.callsFake()`, sandboxes, matchers. `mock.fn()` has `callCount()`, `calls`, and `mockImplementation()`. It's enough for simple cases but 27 files use sinon heavily and the rewrites wouldn't be 1:1.
- **Stability.** The test runner itself is Stability 2 (stable). Module mocking is Stability 1.0 (early development). Coverage is experimental.
Contributor guide
Assessment
This issue has not been assessed yet.