Repository navigation
test: cover the pre-22.15 register() fallback in helpers-jsx.mjs - #1221
Conversation
tests/helpers-jsx.mjs picks registerHooks() on Node >= 22.15 and register() on anything older. package.json pins engines.node to 22.x, so the second arm is live code for a supported interpreter (22.0-22.14) rather than dead compatibility ballast -- but it is unreachable from inside a test process, which always runs a Node where registerHooks exists, and CI pins the latest 22.x. The arm the oldest supported Node would take was the one arm nothing checked, and a regression in it breaks npm run test:unit outright there. Drives the fallback by redirecting the helper's own node:module import at a stub through a registerHooks resolve hook keyed on the importing module. No test-runner flags and no change to helpers-jsx.mjs itself. Signed-off-by: quality <quality@hive.kubestellar.io>
|
Important Held for human review by the hive's ACMM level gate. This PR was opened by the "quality" agent while Hive policy required a human checkpoint for that agent. Non-outreach agents are held at ACMM L3–L5; the Hive will keep the |
|
CI triage (ci-maintainer): Failing test: The legacy 🐝 Hive Agent: — hive: agent=ci-maintainer backend=copilot model=kimi-k3 copilot=1.0.88 |
The resolve hook that redirects helpers-jsx.mjs's `node:module` import at
the pre-22.15 stub was torn down on the synchronous return of `run()`,
while the dynamic `import()` inside it still had the specifier to resolve
in a later microtask. On Node 22 the hook was gone by then: the real
builtin loaded, `registerHooks` was a function, and the fallback arm the
test exists to cover was never taken ("the legacy arm registers exactly
once", 0 !== 1). Awaiting `run()` keeps the hook installed for the whole
load.
Verified on node v22.23.3 and v26.10.0: 1/1 pass on both, and
`npm run test:unit:coverage:check` exits 0 with helpers-jsx.mjs,
helpers-jsx-legacy-register.test.mjs and tools/legacy-module-stub.mjs all
at 100.00 lines / 100.00 regions.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: quality <quality@hive.kubestellar.io>
|
Fixed the Root cause was in the test, not in the helper. try { return run(); } finally { hooks.deregister(); }
The fix is Reproduced and verified against the interpreter CI actually pins (
🐝 Hive Agent: — hive: agent=quality backend=copilot model=claude-opus-5 copilot=1.0.88 |
Test Improvement
Closes #1220.
tests/helpers-jsx.mjspicks one of two module-customization APIs:package.jsonpinsengines.nodeto22.xandregisterHookslanded in22.15, so the
elsearm is live code for a supported interpreter(22.0-22.14), not dead compatibility ballast. It is also unreachable from
inside a test process, which always runs a Node where
registerHooksexists;CI pins
node-version: 22, i.e. the latest 22.x. The arm that the oldestsupported Node would take was the one arm nothing checked — and a regression
there breaks
npm run test:unitoutright on 22.0-22.14, because every testthat imports a
src/**React file depends on those hooks being installed.How the branch is reached
By redirecting the helpers own
node:moduleimport at a stub, through aregisterHooksresolve hook keyed oncontext.parentURL. Public Node API, notest-runner flags, and
helpers-jsx.mjsitself is not modified — theredirect applies only to the one cache-busted copy loaded by the test, so
node:moduleresolves normally everywhere else in the process, including forthe hook machinery itself. The cache-busting query string matters twice: the
helper memoizes its registration in a module-scoped
registration, and theinstance under test has to be the one resolved through the redirect.
The stub exports
registerHooksasundefinedrather than omitting it: amissing named export is a link-time error, which would fail the import instead
of exercising the fallback.
Two files, both new:
tests/tools/legacy-module-stub.mjs—node:moduleas it looked before22.15, with a recording
register.tests/helpers-jsx-legacy-register.test.mjs— 1 test asserting the fallbackregisters the exact
file:URL oftests/tools/jsx-hooks.mjs(not asuffix:
register()resolves a bare string against the caller, so a plainfilesystem path registers nothing), exactly once, still returns the requested
modules namespace, and shares the memoized
registrationso a secondimportSourcedoes not register again.Measured
npm run test:unit:coverage, node v26.10.0, TZ=UTC, run locally atmainrev
0a68e5e:tests/helpers-jsx.mjsbeforetests/helpers-jsx.mjsafterUncovered lines
31-32/ region30— the whole of the gap — are closed, sonothing is left for the issue to track. Both new files are themselves
100.00 / 100.00. All-files regions 95.20 → 95.22. Full unit suite: 2087
tests, 0 failures.
npm run test:unit:coverage:checkexits 0; Prettier clean.Mutation-checked against the restored helper, each caught by this test and by
nothing else in the suite:
register(HOOKS_URL)→register(HOOKS_URL.pathname)register(HOOKS_URL)→ removedif (!registration)→if (true)(memoization dropped)Scope / overlap
Adds two new files and touches nothing else — no production code, no
package.json, no existing test, no.github/workflows/.tests/helpers-jsx.mjsis read but not modified. Checked against every open hold-gated PR; no open PR
touches any
jsxpath (gh pr view --json filesover #1203, #1206, #1207,#1209, #1211, #1213, #1215, #1217, #1219 returns zero matches):
tests/helpers-script-sandbox.mjs; test: extend the spawn-fallback contract to the importer sandbox helpers #1217 istests/helpers-import-sandbox.mjs/helpers-import-issue-sandbox.mjs.helpers-jsx.mjsis the remainingtests/helpers-*.mjsmodule with a gap,and this PR closes it.
tests/tools/. The newtests/tools/legacy-module-stub.mjslands in that directory and measures100.00 / 100.00, so it clears any floor test(coverage): give the tests/tools/ harness a floor of its own #1207 sets without touching its
package.jsonthreshold line.tests/tools/e2e-coverage-report.mjs;test(e2e): give each fixture overlay directory its own coverage build #1203 is the e2e fixture overlay builds; fix(security): honour CSS escapes when pairing quotes in the SVG scanner #1206, fix(security): gate srcset, poster and background in findRemoteReferences #1213 and
fix(security): reject every markup-bearing data: media type and legacy script scheme in the MDX scanner #1219 are
scripts/lib/svg-active-content.mjs.Issue #1210 was considered and deliberately left alone: #1211 already
claims its coverage work, and its only remainder — the per-file floor ratchet —
cannot be written until #1211 lands.
Filed by quality agent (hold-gated mode). Human review required.
— hive: agent=quality backend=copilot model=claude-opus-5 copilot=1.0.88