Files
msd-core/tests/npm-version-check-diagnosis.test.cjs
Jakub Zych a9a7a328e6 refactor: hard-fork GSD -> MSD (Make Software Done)
Mechanical rename produced by scripts/msd-rename.cjs: gsd/Gsd/GSD -> msd/Msd/MSD
across contents and paths, upstream package/repo coordinates -> @golem15/msd-core
and golem15com/msd-core. Deep links into upstream history, sibling upstream
packages, the GSD-2 import feature, CHANGELOG.md and .changeset/ are kept as-is.

Hand edits on top: MSD block-letter banner and logos, LICENSE copyright line,
package/plugin identity, regenerated lockfile, install-tree fixtures, derived
registries and benchmark baseline; migration checksum baseline re-locked
(MSD keeps its own install state, so no install had applied the old sums);
sort-order and regex-escaped expectations in tests adjusted.
2026-10-06 01:47:40 +02:00

75 lines
3.8 KiB
JavaScript

'use strict';
/**
* Regression coverage for #4460 (discovered blocking this PR's own Windows
* CI, unrelated to this PR's actual diff -- fixed inline per this repo's
* no-defer policy): scripts/check-env.cjs's npm-version check used to
* collapse every spawnSync failure mode into one message, "npm binary not
* found on PATH" -- including a TIMEOUT under CI load, which looks
* identical to a genuine ENOENT (exitCode stays non-zero, stdout stays
* empty either way). Confirmed live, twice, on real Windows CI: the check
* now correctly reports "timed out under CI load" for exactly that case.
*
* describeNpmVersionCheckFailure is the extracted, pure reason-selection
* logic. It takes a plain result object shaped like this repo's canonical
* OS-shell-projection seam's SpawnResultOutput (execNpm,
* src/shell-command-projection.cts) -- same `timedOut` (error.code ===
* 'ETIMEDOUT') semantics -- but check-env.cjs computes that shape inline
* rather than importing the seam itself: that seam's compiled output
* (msd-core/bin/lib/*.cjs) does not exist yet when check-env.cjs runs as
* its own standalone pre-`npm ci` CI step (an earlier version of this fix
* imported it directly and crashed every real CI job with
* MODULE_NOT_FOUND). Kept in scripts/lib/ (not scripts/check-env.cjs
* itself, which runs its CLI unconditionally on require) so it can be
* required directly here without triggering a real environment check.
*/
const { describe, test } = require('node:test');
const assert = require('node:assert/strict');
const { describeNpmVersionCheckFailure } = require('../scripts/lib/npm-version-check-diagnosis.cjs');
describe('describeNpmVersionCheckFailure (#4460)', () => {
test('a genuine ENOENT (npm truly absent) reports the original message', () => {
const result = { exitCode: 127, stdout: '', stderr: 'npm: not found', signal: null, error: Object.assign(new Error('spawnSync npm ENOENT'), { code: 'ENOENT' }), timedOut: false };
assert.equal(
describeNpmVersionCheckFailure(result),
'npm binary not found on PATH',
);
});
test('a timed-out spawn is reported as a timeout, not a missing binary', () => {
const result = { exitCode: 1, stdout: '', stderr: '', signal: 'SIGTERM', error: Object.assign(new Error('ETIMEDOUT'), { code: 'ETIMEDOUT' }), timedOut: true };
const reason = describeNpmVersionCheckFailure(result);
assert.match(reason, /timed out under CI load/);
assert.doesNotMatch(reason, /^npm binary not found on PATH$/);
});
test('timedOut is authoritative even without an ENOENT-shaped error object', () => {
// Mirrors what execNpm/_spawnResult actually produces for a timeout:
// error is set (spawnSync always populates it when `timeout` fires),
// but its code is ETIMEDOUT, not ENOENT -- timedOut is what matters.
const result = { exitCode: 1, stdout: '', stderr: '', signal: 'SIGTERM', error: null, timedOut: true };
assert.match(describeNpmVersionCheckFailure(result), /timed out under CI load/);
});
test('a non-zero exit with no stdout and no timeout is reported with the actual exit code', () => {
const result = { exitCode: 1, stdout: '', stderr: '', signal: null, error: null, timedOut: false };
assert.equal(
describeNpmVersionCheckFailure(result),
'npm --version exited 1 with no usable output',
);
});
test('exitCode 0 with no stdout gets its own message, not the "not found" fallback', () => {
// npm ran and exited cleanly but printed nothing -- distinct from every
// other branch (all of which involve a failed/absent spawn); must not be
// misdescribed as "not found on PATH" when the binary plainly ran.
const result = { exitCode: 0, stdout: '', stderr: '', signal: null, error: null, timedOut: false };
assert.equal(
describeNpmVersionCheckFailure(result),
'npm --version exited 0 but produced no output',
);
});
});