Add support for Node.js 22 and 24 - #542
Merged
Merged
Conversation
mocha 10.x bundles yargs 16.2.0, whose CJS entry point is an extensionless file reached via the exports "require" condition while the package itself declares "type": "module". Node 26's stricter require(esm) handling trusts that "type" field unconditionally and tries to load the file as ESM, which crashes on its own bare require() call. This broke test:example:babel and test:example:node-esm under the newly added Node "current" CI job. Since node:test has been available (experimentally) since Node 16.17, swap both example projects to it instead, removing the mocha/chai/ yargs dependency chain entirely. This works uniformly across the 16-26 Node matrix. Mirrors the identical fix already applied to quibble's own example projects. Along the way, discovered that node:test's top-level beforeEach/ afterEach hooks do not cascade into nested describe() blocks (unlike mocha), so the babel example's shared test/helper.js was changed from registering global hooks to exporting a setup()/teardown() pair that the spec's own local beforeEach/afterEach call explicitly. Verified npm test passes fully (all example projects included) on Node 20.16.0, 22.14.0, and 24.14.1 (asdf) and 26.9.0 "current" (Docker node:current), with a locally-built fix for quibble's separate Node 22+ ESM loader bug installed for the run. quibble's fix (testdouble/quibble#more-node-versions) is not yet published to npm, so testdouble.js's own package.json still resolves the published, unfixed quibble@0.9.2 until that happens.
To bring Node 22+ compatibility.
Mirrors the node-esm example conversion. mocha 10 crashes on Node 26 (yargs 16), and mocha 11+/12 constrain the supported Node range, so dropping it removes the last mocha usage in the repo. The example still runs without --loader to exercise auto-registration.
rosston
marked this pull request as ready for review
September 21, 2026 19:04
This was referenced Sep 21, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #530.
Why
CI now runs against Node 22, 24 and
current(26.x) in addition to 16, 18 and 20, on both Ubuntu and Windows. Adding those versions surfaced three separate problems, and this PR fixes all of them so the full matrix is green.?__quibble=Nquery string on Node 22 and later, which could make stub substitutions silently miss. Fixed upstream in quibble 0.10.0.require(esm)handling tries to load as ESM. Thebabel,node-esmandnode-esm-auto-loaderexamples died on startup before running a single test.npm testwas silently broken. Three scripts (test:esm-auto-loader,test:no-loader-esm,test:example-esm-auto-loader) decide what to run by callingtest/esm-lib/supports-auto-load.js. That path has never existed in this repo; the helper lives attest/support/. The wrong path came in with the 3.19.0 release commit. Becausenodefailed on the missing file, the||fallback always ran, sotest:no-loader-esmran on every Node version, andtest:esm-auto-loaderand thenode-esm-auto-loaderexample had been dropped fromnpm test, so CI never exercised them.What changed
^0.9.2→^0.10.0. The example lockfiles were refreshed too (thefile:dependency stores a snapshot of this package's dependencies, so they had gone stale).node:test.babel,node-esmandnode-esm-auto-loaderno longer use mocha (or chai). This is the last mocha usage in the repo. Thebabelexample's shared helper now exportssetup()/teardown()instead of registering top-level hooks, becausenode:testtop-level hooks don't cascade into nesteddescribeblocks.node-esm-auto-loaderstill runs without--loader, since testing auto-registration is its whole point.test/support/supports-auto-load.js. I restoredcross-envontest:esm-auto-loader, which the 3.19.0 release commit had dropped and which is needed under Windowscmd.exe.test:esm-auto-loaderis back innpm testandtest:example-esm-auto-loaderis back intest:example.The gating now does what it was written to do:
test:no-loader-esmtest:esm-auto-loader, auto-loader exampletest:no-loader-esmThe visible effect is that
test:no-loader-esmno longer runs on Node 18 and later, which is what that script intends.Alternatives considered
^18.18 || ^20.9 || >=21.1, and mocha 12 needs^20.19 || >=22.12. We still support Node 16 (and test 18.20 and 20.16), and thebabelandnode-esmexamples run on all of them, so no mocha release that works on Node 26 also works across the whole matrix.node:testdoes (Node 16.17+), and drops a large dependency tree.||fallback always ran, so nothing was testing what the scripts claimed to. Fixing the path is a one-line change per script and makes the gates real.Known follow-up (not in this PR)
On Node 26, replacing an ES module without
--loaderprintsDEP0205: module.register() is deprecated. Use module.registerHooks() instead, once per process. It is harmless, doesn't fail anything, and doesn't appear on Node 16 through 24. TheModule.register()call is inside quibble, not this repo, so it can't be fixed here.src/can-register-loader.jsonly checks whetherModule.registerexists, and it will need to change together with quibble.Verification
current, on Ubuntu and Windows) pass. The Windows logs show the gating behaving as in the table above, including the auto-loader example passing on Windows for Node 18 andcurrent.Notes for reviewers
package-lock.jsondiffs forbabel,node-esmandnode-esm-auto-loaderare huge (over 30,000 lines removed) because the mocha/chai dependency trees are gone. The substantive changes are thepackage.jsonfiles, the example test files and the rootpackage.jsonscripts.jest,jest-broken,nodeandnode-avalockfile changes are only the refreshedtestdoubleandquibblesnapshot lines.