Files
nextcraft/apps/cli/tests/path-invocation.test.ts
T
CIAgent 1a88ab3199
Release / release (push) Successful in 3m45s
CI / python (push) Successful in 1m52s
CI / node (push) Successful in 1m0s
merge: milestone/v0.8-ship-anywhere -> main (v0.8 complete — Ship Anywhere)
The v0.8 milestone: installable on any Debian-based server via docker
(Gitea registry image, honest sandbox degrade), deb (amd64+arm64,
advisory postinst), and arch-aware binary — with release consistency
enforced by pre-commit hooks + Gitea Actions (3-runner fleet on CT 113,
machine-made releases with the full 8-asset matrix + registry image), the
CLI carrying the full suite (guide, channel-aware doctor), and the admin
runbook (deploy/README.md, evidence-backed recipes).

---ci---
phase: 6
milestone: v0.8
status: complete
requirements:
  covered: [REQ-8-001, REQ-8-002, REQ-8-003, REQ-8-004, REQ-8-005]
  partial: []
---/ci---
2026-09-29 16:04:40 +00:00

41 lines
2.2 KiB
TypeScript

import { test } from "node:test";
import assert from "node:assert/strict";
import { spawnSync } from "node:child_process";
import { cpSync, existsSync, mkdtempSync } from "node:fs";
import { tmpdir } from "node:os";
import { join, dirname } from "node:path";
import { fileURLToPath } from "node:url";
const cliDir = join(dirname(fileURLToPath(import.meta.url)), "..");
const repoRoot = join(cliDir, "..", "..");
const binary = join(repoRoot, "apps", "cli", "dist", "nextcraft-linux-x64");
test("PATH bare-word invocation: installed binary speaks (SEA regression, v0.3.4 bug)", { skip: existsSync(binary) ? false : `built binary missing: ${binary} (run cli:build:binary)` }, () => {
const binDir = mkdtempSync(join(tmpdir(), "nc-pathword-"));
cpSync(binary, join(binDir, "nextcraft"));
const env = {
PATH: [binDir, process.env.PATH].filter(Boolean).join(":"),
HOME: process.env.HOME,
};
// Strip the test-runner's env marker: the child CLI must see a clean env
// (its isDirectRun() probe keys on NODE_TEST_CONTEXT).
const { NODE_TEST_CONTEXT: _stripped, ...rest } = process.env as Record<string, string | undefined>;
void _stripped;
const envClean = { ...rest, ...env } as Record<string, string | undefined>;
const ver = spawnSync("sh", ["-c", "nextcraft --version"], { encoding: "utf8", timeout: 30000, env: envClean });
assert.equal(ver.status, 0, `--version rc: ${ver.status} stderr: ${ver.stderr}`);
assert.ok(ver.stdout.trim().length > 0, "--version must print the version (v0.3.4 was silent)");
const doc = spawnSync("sh", ["-c", "nextcraft doctor"], { encoding: "utf8", timeout: 120000, env: envClean });
assert.equal(doc.status, 0, `doctor rc: ${doc.status} stderr: ${doc.stderr}`);
assert.ok(doc.stdout.includes("environment prerequisites"), "doctor must print its report");
const noArgs = spawnSync("sh", ["-c", "nextcraft"], { encoding: "utf8", timeout: 30000, env: envClean });
assert.equal(noArgs.status, 2, "no args must exit 2");
assert.ok((noArgs.stderr + noArgs.stdout).includes("Usage:"), "no args must print usage");
const bad = spawnSync("sh", ["-c", "nextcraft nosuchcmd"], { encoding: "utf8", timeout: 30000, env: envClean });
assert.equal(bad.status, 2, "unknown command must exit 2");
});