61 lines
2.8 KiB
TypeScript
61 lines
2.8 KiB
TypeScript
import { existsSync, readFileSync, readdirSync, rmSync } from "node:fs";
|
|
import { spawnSync } from "node:child_process";
|
|
import { describe, expect, test } from "bun:test";
|
|
import { repoRoot } from "./config";
|
|
|
|
const dumpDir = "/tmp/unidesk-cli-output";
|
|
|
|
function runOversizedIssueOutput(token: string, explicit = false): { status: number | null; stdout: string; stderr: string } {
|
|
const command = `gh issue view 1890 --repo pikasTech/unidesk --json body ${token}`;
|
|
const script = [
|
|
"import { emitJson } from './scripts/src/output.ts';",
|
|
`emitJson(${JSON.stringify(command)}, {`,
|
|
" command: 'issue view',",
|
|
" repo: 'pikasTech/unidesk',",
|
|
" issue: { number: 1890, title: 'large body', state: 'open', url: 'https://example.invalid/1890', body: 'x'.repeat(30000) },",
|
|
"});",
|
|
].join("\n");
|
|
const args = ["-e", script, "output-test", ...(explicit ? ["--full"] : [])];
|
|
const result = spawnSync("bun", args, { cwd: repoRoot, encoding: "utf8" });
|
|
return { status: result.status, stdout: result.stdout, stderr: result.stderr };
|
|
}
|
|
|
|
function matchingDumps(token: string): string[] {
|
|
if (!existsSync(dumpDir)) return [];
|
|
return readdirSync(dumpDir).filter((name) => name.includes(token));
|
|
}
|
|
|
|
describe("CLI oversized output disclosure", () => {
|
|
test("default oversized output creates no dump and gives the semantic gh text route", () => {
|
|
const token = `nodump-${process.pid}-${Date.now()}`;
|
|
expect(matchingDumps(token)).toEqual([]);
|
|
|
|
const result = runOversizedIssueOutput(token);
|
|
|
|
expect(result.status).toBe(0);
|
|
expect(result.stderr).toBe("");
|
|
const payload = JSON.parse(result.stdout) as { data: { outputTruncated: boolean; dump?: unknown; next: string[]; disclosurePolicy: Record<string, unknown> } };
|
|
expect(payload.data.outputTruncated).toBe(true);
|
|
expect(payload.data.dump).toBeUndefined();
|
|
expect(payload.data.disclosurePolicy).toMatchObject({ defaultCreatesDump: false, dumpCreated: false });
|
|
expect(payload.data.next[0]).toBe("trans gh:/pikasTech/unidesk/issue/1890 cat");
|
|
expect(matchingDumps(token)).toEqual([]);
|
|
});
|
|
|
|
test("explicit full disclosure keeps a protected complete dump", () => {
|
|
const token = `fulldump-${process.pid}-${Date.now()}`;
|
|
expect(matchingDumps(token)).toEqual([]);
|
|
|
|
const result = runOversizedIssueOutput(token, true);
|
|
|
|
expect(result.status).toBe(0);
|
|
expect(result.stderr).toBe("");
|
|
const payload = JSON.parse(result.stdout) as { data: { dump: { path: string }; disclosurePolicy: Record<string, unknown> } };
|
|
expect(payload.data.disclosurePolicy).toMatchObject({ defaultCreatesDump: false, dumpCreated: true });
|
|
expect(existsSync(payload.data.dump.path)).toBe(true);
|
|
expect(readFileSync(payload.data.dump.path, "utf8")).toContain(token);
|
|
rmSync(payload.data.dump.path, { force: true });
|
|
expect(matchingDumps(token)).toEqual([]);
|
|
});
|
|
});
|