Repository navigation
test: extend the spawn-fallback contract to the importer sandbox helpers - #1217
Merged
mrbobbytables merged 2 commits intoOct 9, 2026
Merged
Conversation
tests/helpers-spawn-fallbacks.test.mjs pins the spawnSync normalisation contract for runScriptWithFixtures, runScriptWithFetchMock and runWithGhStub. runImportArchitectures and runImportArchitectureIssue apply the same status ?? 1 / stdout ?? '' / stderr ?? '' normalisation and were left out, so all three fallbacks in each were uncovered. Both helpers spawn process.execPath, an absolute path, so the established withoutPath lever cannot stop the child from starting; process.execPath is a writable property, so pointing it at a path that does not exist is the equivalent and is restored in a finally. Also covers the mkfifo guard in helpers-import-sandbox.mjs, which the helper documents as a broken fixture rather than a skip but which nothing checked. Closes #1216 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: quality <quality@hive.kubestellar.io>
Contributor
Author
|
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 |
CodeQL flagged the `collision.replace(/\./g, '\\.')` escape as incomplete: it escapes dots but leaves backslashes and every other regex metacharacter intact. The assertion only ever needed to show that the failing path is named in the message, so a plain substring check expresses that directly and removes the partial-sanitisation pattern rather than extending it. Signed-off-by: quality <quality@hive.kubestellar.io>
This was referenced Oct 8, 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.
Test Improvement
Closes #1216.
tests/helpers-spawn-fallbacks.test.mjspins one contract shared by everyspawn-based sandbox helper: the helper normalises the
spawnSyncresult beforehanding it to a test (
status ?? 1,stdout ?? '',stderr ?? ''), so a childthat never started surfaces as a plain non-zero run with empty output rather
than leaking
null/undefinedinto an assertion.spawnSyncreports a failedspawn as
status: nullwithstdout/stderrundefined rather than throwing,so that normalisation is the whole difference between "the importer failed" and
"the harness could not start it".
That file covers
runScriptWithFixtures,runScriptWithFetchMockandrunWithGhStub.runImportArchitecturesandrunImportArchitectureIssuewereleft out, and they back the only coverage the two importers have —
import-architectures.test.mjs,import-architectures-fallbacks.test.mjs,import-architecture-issue.test.mjsandimport-architecture-issue-project-href.test.mjs.Adds
tests/helpers-import-sandbox-fallbacks.test.mjs, 4 tests:runImportArchitecturesdegrades cleanly —statusis1,stdout/stderrare'', and the sandbox readers still work: the fixturethe helper staged before the spawn is readable, while the record only the
importer would have written is absent. That is what keeps a harness fault
distinguishable from an importer that ran and wrote nothing.
runImportArchitectureIssuedegrades cleanly — same contract;issue.jsonsurvives a spawn that never happened,catalog.jsondoes not.mkfifoguard fails loudly — the helper shells out tomkfifobecause Node has no binding for it and treats a non-zero exit as a broken
fixture rather than a skip, but nothing checked that. A silent skip would let
import-architectures-fallbacks.test.mjs's "a special file in images/ isdropped by the walk" pass against a tree that never contained a special file.
The test asserts the failing path and
mkfifo's own stderr reach themessage, since without the latter it cannot say why.
Two notes on how the failures are induced
The established
withoutPathlever does not work here: both helpers spawnprocess.execPath, an absolute path, so emptyingPATHcannot stop the childfrom starting.
process.execPathis a writable, configurable property, sopointing it at a path that does not exist is the equivalent lever, restored in a
finally.node --testruns the tests within a file sequentially, so nosibling test observes the gap.
runImportArchitecturesthrows before it can return acleanup()handle when aFIFO fixture fails, so the temp directory it had already created would leak.
Both helpers place their sandbox with
mkdtempSync(join(tmpdir(), …))andos.tmpdir()re-readsTMPDIRon every call, so the test redirectsTMPDIRata directory it owns and removes it afterwards. The fourth test guards that
cleanup itself, through both restore paths — an absent
TMPDIRhas to come backabsent rather than as the string
"undefined", whichos.tmpdir()would thentreat as a relative directory name.
Measured
npm run test:unit:coverage, node v26.10.0, TZ=UTC, run locally at593b9fe(this branch's base):
tests/helpers-import-sandbox.mjsbeforetests/helpers-import-sandbox.mjsaftertests/helpers-import-issue-sandbox.mjsbeforetests/helpers-import-issue-sandbox.mjsafterBoth files reach 100/100, so the issue's three boxes are all ticked and nothing
is left for it to track. The new test file is itself 100.00 / 100.00. All-files
regions 95.20 → 95.29. Full unit suite: 2090 tests, 0 failures.
npm run test:unit:coverage:checkexits 0; Prettier clean.Each fallback was mutation-checked: dropping
?? 1fromhelpers-import-sandbox.mjsfails the first test, and nothing else in the suitenotices.
Scope / overlap
Adds one new file and touches nothing else — no production code, no
package.json, no existing test, no.github/workflows/. Checked against everyopen hold-gated PR:
tests/helpers-script-sandbox-fallbacks.test.mjsforrunScriptInSandboxintests/helpers-script-sandbox.mjs. Different helper, different module,different new file. Together they finish the contract across all six
tests/helpers-*.mjssandbox modules.tests/tools/e2e-coverage-report.mjs.tests/tools/harness floor; its per-file floor is scoped totests/tools/and these two helpers aretests/helpers-*, so itspackage.jsonthreshold line is untouched here.scripts/lib/svg-active-content.mjs.Filed by quality agent (hold-gated mode). Human review required.
— hive: agent=quality backend=copilot model=claude-opus-5 copilot=1.0.88