Files
nextcraft/apps/cli/tests/guide.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

68 lines
2.6 KiB
TypeScript

// guide command tests (v0.8 P4, D-072/G-210).
import { test } from "node:test";
import assert from "node:assert/strict";
import { run } from "../src/index.ts";
import { testCtx } from "./helpers.ts";
test("guide: overview (default) lists all channels + ends at doctor/verify", async () => {
const ctx = testCtx();
const code = await run(["guide"], ctx);
assert.equal(code, 0);
const out = ctx.out();
assert.ok(out.includes("DOCKER"), "names the docker channel");
assert.ok(out.includes("DEB"), "names the deb channel");
assert.ok(out.includes("BINARY"), "names the binary channel");
assert.ok(out.includes("doctor"), "ends at doctor/verify");
});
test("guide: every topic routes + carries its channel's recipe", async () => {
const topics: Array<[string, string[]]> = [
["docker", ["docker run", "8420", "SANDBOX FABRIC", "seccomp"]],
["deb", ["dpkg -i", "Recommends", "deploy --service"]],
["binary", ["install.sh", "aarch64", "deploy --service"]],
["upgrade", ["docker pull", "dpkg -i", "idempotent"]],
["troubleshooting", ["JSON 404", "8420", "hecksum"]],
];
for (const [topic, markers] of topics) {
const ctx = testCtx();
assert.equal(await run(["guide", topic], ctx), 0, `topic ${topic} exits 0`);
for (const m of markers) {
assert.ok(ctx.out().includes(m), `topic ${topic} mentions ${m}`);
}
}
});
test("guide: unknown topic exits 2 with the topic list", async () => {
const ctx = testCtx();
assert.equal(await run(["guide", "warp"], ctx), 2);
assert.ok(ctx.err().includes("unknown guide topic: warp"));
assert.ok(ctx.err().includes("docker | deb | binary"));
});
test("guide: more than one topic is a usage error (exit 2)", async () => {
const ctx = testCtx();
assert.equal(await run(["guide", "docker", "deb"], ctx), 2);
});
test("guide: docker-mode tail names the in-container commands", async () => {
const ctx = testCtx({
env: { ...process.env, NC_CONTAINER: "1" } as Record<string, string | undefined>,
});
assert.equal(await run(["guide", "docker"], ctx), 0);
assert.ok(ctx.out().includes("docker image detected"), "container-aware tail");
assert.ok(ctx.out().includes("nextcraft doctor"), "points at in-container commands");
});
test("guide: offline-first — forge URLs are pointers (https), never fetches", async () => {
const ctx = testCtx();
await run(["guide", "overview"], ctx);
await run(["guide", "binary"], ctx);
// Any URL in the text is a pointer for the HUMAN; the command itself
// performs no I/O (embedded text only).
const out = ctx.out();
if (out.includes("http")) {
assert.ok(out.includes("https://"), "URLs are https pointers");
}
});