fix: 收敛 trans 顶层帮助输出
This commit is contained in:
@@ -3,15 +3,74 @@ import { describe, expect, test } from "bun:test";
|
||||
import { repoRoot } from "./config";
|
||||
import { sshHelp, sshHelpScope } from "./help";
|
||||
|
||||
describe("ssh download scoped help", () => {
|
||||
test("selects only the exact help-first download scope", () => {
|
||||
type RenderedHelp = {
|
||||
ok: boolean;
|
||||
command: string;
|
||||
data: {
|
||||
command?: string;
|
||||
scope?: string;
|
||||
runtime?: { repoRoot: string };
|
||||
routeSyntax?: Record<string, string> | string;
|
||||
operationGroups?: Record<string, string>;
|
||||
scopedHelp?: { availableOperationCount: number };
|
||||
usage?: string[];
|
||||
outputTruncated?: boolean;
|
||||
dump?: unknown;
|
||||
};
|
||||
};
|
||||
|
||||
function runTransHelp(...args: string[]): { stdout: string; rendered: RenderedHelp } {
|
||||
const result = spawnSync("bun", ["scripts/ssh-cli.ts", ...args], {
|
||||
cwd: repoRoot,
|
||||
env: {
|
||||
...process.env,
|
||||
UNIDESK_SSH_ENTRYPOINT: "trans",
|
||||
UNIDESK_TRANS_REPO_ROOT: repoRoot,
|
||||
},
|
||||
encoding: "utf8",
|
||||
});
|
||||
expect(result.status).toBe(0);
|
||||
expect(result.stderr).toBe("");
|
||||
return { stdout: result.stdout, rendered: JSON.parse(result.stdout) as RenderedHelp };
|
||||
}
|
||||
|
||||
describe("ssh bounded progressive help", () => {
|
||||
test("selects exact help-first operation scopes", () => {
|
||||
expect(sshHelpScope(["ssh", "--help", "download"])).toBe("download");
|
||||
expect(sshHelpScope(["ssh", "help", "download"])).toBe("download");
|
||||
expect(sshHelpScope(["ssh", "help", "apply-patch"])).toBe("apply-patch");
|
||||
expect(sshHelpScope(["ssh", "--help", "ps"])).toBe("ps");
|
||||
expect(sshHelpScope(["ssh", "--help"])).toBeUndefined();
|
||||
expect(sshHelpScope(["ssh", "--help", "unknown"])).toBeUndefined();
|
||||
expect(sshHelpScope(["ssh", "NC01:k3s", "--help"])).toBeUndefined();
|
||||
expect(sshHelpScope(["ssh", "--help", "download", "extra"])).toBeUndefined();
|
||||
});
|
||||
|
||||
test("keeps the top-level model compact while indexing routes and every scoped operation", () => {
|
||||
const top = sshHelp() as {
|
||||
routeSyntax: Record<string, string>;
|
||||
operationGroups: Record<string, string>;
|
||||
scopedHelp: { command: string; availableOperationCount: number };
|
||||
outputTruncated?: boolean;
|
||||
};
|
||||
const serialized = JSON.stringify(top);
|
||||
const grouped = Object.values(top.operationGroups).flatMap((value) => value.split(" | "));
|
||||
|
||||
expect(Buffer.byteLength(serialized, "utf8")).toBeLessThan(6_144);
|
||||
expect(top.outputTruncated).toBeUndefined();
|
||||
expect(top.routeSyntax.general).toContain("<route> <operation>");
|
||||
expect(top.routeSyntax.k3sWorkload).toContain(":<namespace>:<workload>");
|
||||
expect(top.routeSyntax.windowsWorkspace).toContain(":win");
|
||||
expect(top.operationGroups.patch).toBe("apply-patch | apply-patch-v1");
|
||||
expect(top.operationGroups.transfer).toBe("upload | download");
|
||||
expect(new Set(grouped).size).toBe(top.scopedHelp.availableOperationCount);
|
||||
expect(top.scopedHelp.command).toContain("--help <operation>");
|
||||
for (const operation of grouped) {
|
||||
const scope = sshHelpScope(["ssh", "--help", operation]);
|
||||
expect(scope).toBe(operation);
|
||||
expect(Buffer.byteLength(JSON.stringify(sshHelp(scope)), "utf8")).toBeLessThan(6_144);
|
||||
}
|
||||
});
|
||||
|
||||
test("keeps download help bounded and discloses the executing source root", () => {
|
||||
const scoped = sshHelp("download") as {
|
||||
scope: string;
|
||||
@@ -20,13 +79,11 @@ describe("ssh download scoped help", () => {
|
||||
examples: Record<string, string>;
|
||||
contract: { pathOrder: string[]; transport: string; verification: { automatic: boolean } };
|
||||
};
|
||||
const full = sshHelp() as { usage: string[] };
|
||||
const serialized = JSON.stringify(scoped);
|
||||
|
||||
expect(scoped.scope).toBe("download");
|
||||
expect(scoped.usage.length).toBeLessThanOrEqual(4);
|
||||
expect(scoped.usage.length).toBeLessThan(full.usage.length);
|
||||
expect(Buffer.byteLength(serialized, "utf8")).toBeLessThan(10_240);
|
||||
expect(Buffer.byteLength(serialized, "utf8")).toBeLessThan(6_144);
|
||||
expect(serialized).not.toContain("git exact-commit");
|
||||
expect(scoped.runtime.repoRoot).toBe(repoRoot);
|
||||
expect(scoped.runtime.cliPath).toBe(`${repoRoot}/scripts/ssh-cli.ts`);
|
||||
@@ -40,46 +97,32 @@ describe("ssh download scoped help", () => {
|
||||
"trans NC01:k3s:hwlab-v03:hwlab-cloud-api:hwlab-cloud-api download /tmp/trace.json ./trace.json",
|
||||
);
|
||||
expect(scoped.examples.windowsDrive).toContain("D:\\tmp\\trace.json");
|
||||
expect(scoped.examples.explicitWorktree).toBe(
|
||||
`UNIDESK_TRANS_REPO_ROOT=${repoRoot} trans NC01:k3s:hwlab-v03:hwlab-cloud-api:hwlab-cloud-api download /tmp/trace.json ./trace.json`,
|
||||
);
|
||||
});
|
||||
|
||||
test("renders the original trans command without stdout dump fallback", () => {
|
||||
const result = spawnSync("bun", ["scripts/ssh-cli.ts", "--help", "download"], {
|
||||
cwd: repoRoot,
|
||||
env: {
|
||||
...process.env,
|
||||
UNIDESK_SSH_ENTRYPOINT: "trans",
|
||||
UNIDESK_TRANS_REPO_ROOT: repoRoot,
|
||||
},
|
||||
encoding: "utf8",
|
||||
});
|
||||
test("renders compact top-level and scoped help without dump fallback", () => {
|
||||
const top = runTransHelp("--help");
|
||||
expect(Buffer.byteLength(top.stdout, "utf8")).toBeLessThan(6_144);
|
||||
expect(top.rendered.ok).toBe(true);
|
||||
expect(top.rendered.command).toBe("trans --help");
|
||||
expect(top.rendered.data.outputTruncated).toBeUndefined();
|
||||
expect(top.rendered.data.dump).toBeUndefined();
|
||||
expect(top.rendered.data.operationGroups?.transfer).toContain("download");
|
||||
|
||||
expect(result.status).toBe(0);
|
||||
expect(result.stderr).toBe("");
|
||||
expect(Buffer.byteLength(result.stdout, "utf8")).toBeLessThan(10_240);
|
||||
const rendered = JSON.parse(result.stdout) as {
|
||||
ok: boolean;
|
||||
command: string;
|
||||
data: { scope: string; runtime: { repoRoot: string }; usage: string[]; outputTruncated?: boolean };
|
||||
};
|
||||
expect(rendered.ok).toBe(true);
|
||||
expect(rendered.command).toBe("trans --help download");
|
||||
expect(rendered.data.scope).toBe("download");
|
||||
expect(rendered.data.runtime.repoRoot).toBe(repoRoot);
|
||||
expect(rendered.data.usage.length).toBeLessThanOrEqual(4);
|
||||
expect(rendered.data.outputTruncated).toBeUndefined();
|
||||
const routeTop = runTransHelp("NC01:k3s", "--help");
|
||||
expect(routeTop.rendered.command).toBe("trans NC01:k3s --help");
|
||||
expect(routeTop.rendered.data.outputTruncated).toBeUndefined();
|
||||
expect(routeTop.rendered.data.operationGroups).toEqual(top.rendered.data.operationGroups);
|
||||
|
||||
const unified = spawnSync("bun", ["scripts/cli.ts", "ssh", "--help", "download"], {
|
||||
cwd: repoRoot,
|
||||
env: process.env,
|
||||
encoding: "utf8",
|
||||
});
|
||||
expect(unified.status).toBe(0);
|
||||
expect(unified.stderr).toBe("");
|
||||
const unifiedRendered = JSON.parse(unified.stdout) as { data: { scope: string; runtime: { repoRoot: string } } };
|
||||
expect(unifiedRendered.data.scope).toBe("download");
|
||||
expect(unifiedRendered.data.runtime.repoRoot).toBe(repoRoot);
|
||||
const applyPatch = runTransHelp("--help", "apply-patch");
|
||||
expect(applyPatch.rendered.command).toBe("trans --help apply-patch");
|
||||
expect(applyPatch.rendered.data.scope).toBe("apply-patch");
|
||||
expect(applyPatch.rendered.data.usage?.[0]).toContain("apply-patch");
|
||||
expect(applyPatch.rendered.data.outputTruncated).toBeUndefined();
|
||||
|
||||
const download = runTransHelp("--help", "download");
|
||||
expect(download.rendered.command).toBe("trans --help download");
|
||||
expect(download.rendered.data.scope).toBe("download");
|
||||
expect(download.rendered.data.runtime?.repoRoot).toBe(repoRoot);
|
||||
expect(download.rendered.data.outputTruncated).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user