Skip to content

test: replace mocha with the Node.js built-in test runner - #1042

Merged
sajikix merged 3 commits into
mainfrom
refactor/replace-mocha-with-node-test
Sep 4, 2026
Merged

sajikix merged 3 commits into
mainfrom
refactor/replace-mocha-with-node-test

Conversation

@sajikix

@sajikix sajikix commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Summary

Replaces mocha with the Node.js built-in test runner (node --test).

The existing tests only used describe / it / beforeEach and node:assert, so mocha could be dropped without changing a single line of test code.

Changes

File Change
test/setup.mjs (new) Exposes the node:test API as globals
package.json test script → node --test --test-timeout=10000 --import ./test/setup.mjs "test/**/*-test.js", mocha removed from devDependencies
eslint.config.mjs globals.mocha replaced with explicit declarations of the six globals that test/setup.mjs injects
pnpm-lock.yaml mocha and its transitive dependencies removed (-445 lines)

Why the global injection

ESLint's RuleTester (used by test/plugin/react/rules/*-test.js) looks up the global describe / it and falls back to a synchronous handler when they are missing. With node:test these are module exports rather than globals, so without the injection the rule tests would run but report no test count. Assigning them to globalThis via --import keeps RuleTester reporting each case individually and requires no changes to the test files.

Why the timeout was raised from 5s to 10s

node --test runs test files in parallel, unlike mocha's serial execution, so the wall-clock time of an individual test increases under CPU contention. With the original 5s limit one test was actually cancelled.

Verification

  • pnpm test → 208 tests / 69 suites / 208 pass / 0 fail / 0 cancelled
  • pnpm lint → no errors

No workflow changes are needed: CI and the release workflow both just call pnpm test.

Test files only used `describe`/`it`/`beforeEach` and `node:assert`, so
mocha can be dropped without touching any test code. `test/setup.mjs`
exposes the `node:test` API as globals, which also keeps ESLint's
`RuleTester` working since it looks up global `describe`/`it`.

The timeout is raised from 5s to 10s because `node --test` runs test
files in parallel, unlike mocha's serial execution.
Copilot AI lite review requested due to automatic review settings September 1, 2026 09:02

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR migrates the repo’s test execution from mocha to Node.js’s built-in test runner (node --test) while keeping the existing test files unchanged by injecting node:test helpers (describe/it/hooks) as globals.

Changes:

  • Added test/setup.mjs to expose node:test APIs on globalThis via --import.
  • Updated package.json to run tests with node --test (and removed mocha from devDependencies).
  • Updated ESLint globals to remove globals.mocha and declare the injected test globals explicitly; lockfile updated accordingly.

Reviewed changes

Copilot reviewed 3 out of 4 changed files in this pull request and generated 1 comment.

File Description
test/setup.mjs Adds a preload module that injects node:test suite/test/hook functions as globals for existing tests and RuleTester.
package.json Switches the test script to node --test with preload and increases timeout; removes mocha dependency.
eslint.config.mjs Replaces globals.mocha with explicit describe/it/hook global declarations to match the new test setup.
pnpm-lock.yaml Removes mocha and its transitive dependencies from the lockfile.
Files not reviewed (1)
  • pnpm-lock.yaml: Generated file

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread eslint.config.mjs Outdated
Comment on lines +14 to +20
// Injected by test/setup.mjs (see the `test` npm script)
describe: "readonly",
it: "readonly",
before: "readonly",
after: "readonly",
beforeEach: "readonly",
afterEach: "readonly",

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅

`describe`/`it`/hooks only exist while running `node --test --import
./test/setup.mjs`, so declaring them for every file misrepresents the
setup. Move them into a `files: ["test/**"]` block.
Comment thread test/setup.mjs Outdated
*/
import { describe, it, before, after, beforeEach, afterEach } from "node:test";

Object.assign(globalThis, {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at

import assert from "assert";
, it looks like assert is coming from the node:assert module there as well, so it might be nice to be consistent about this — either importing the module in each test file, or assigning them all at once here.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed — switched to explicit imports in b2c08d2. Each test file now imports describe/it from node:test (same as assert), and setup.mjs only wires RuleTester to node:test via its public API, so no globals are injected anymore.

Test files already import `assert` from a module, so import
`describe`/`it` from `node:test` the same way instead of relying on
globals injected by `test/setup.mjs`. The setup module now only wires
ESLint's `RuleTester` to `node:test` via its public `describe`/`it`
static properties, since `RuleTester` resolves them on its own and
cannot see imports made in test files. This also removes the need for
any test-specific globals in the ESLint config.

@nus3 nus3 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM~

@sajikix
sajikix merged commit 36e33fe into main Sep 4, 2026
4 checks passed
@sajikix
sajikix deleted the refactor/replace-mocha-with-node-test branch September 4, 2026 05:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants