Initial Commit
This commit is contained in:
164
packages/api-stack/api/wasm-compiler-javy/src/bin/cli.test.ts
Normal file
164
packages/api-stack/api/wasm-compiler-javy/src/bin/cli.test.ts
Normal file
@@ -0,0 +1,164 @@
|
||||
import { mkdtempSync, rmSync } from "node:fs";
|
||||
import { tmpdir } from "node:os";
|
||||
import { dirname, join, resolve } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { describe, expect, it } from "@suaveplan/testing/runner";
|
||||
import { parseCliArgs, runCli } from "./cli.js";
|
||||
|
||||
const HERE = dirname(fileURLToPath(import.meta.url));
|
||||
const FIXTURE = resolve(HERE, "../../tests/fixtures/tiny-plugin/src/index.ts");
|
||||
|
||||
describe("parseCliArgs", () => {
|
||||
it("parses entry + outDir", { timeout: 5000 }, () => {
|
||||
const a = parseCliArgs(["./entry.ts", "--out-dir", "/tmp/out"]);
|
||||
expect(a.entry).toBe("./entry.ts");
|
||||
expect(a.outDir).toBe("/tmp/out");
|
||||
expect(a.optimizeFor).toBe("size");
|
||||
expect(a.sourcemaps).toBe(false);
|
||||
expect(a.help).toBe(false);
|
||||
});
|
||||
|
||||
it("parses --optimize-for and --sourcemaps", { timeout: 5000 }, () => {
|
||||
const a = parseCliArgs([
|
||||
"./entry.ts",
|
||||
"--out-dir",
|
||||
"/tmp/out",
|
||||
"--optimize-for",
|
||||
"speed",
|
||||
"--sourcemaps",
|
||||
]);
|
||||
expect(a.optimizeFor).toBe("speed");
|
||||
expect(a.sourcemaps).toBe(true);
|
||||
});
|
||||
|
||||
it("raises on invalid optimize-for", { timeout: 5000 }, () => {
|
||||
expect(() =>
|
||||
parseCliArgs(["x.ts", "--out-dir", "out", "--optimize-for", "tiny"])
|
||||
).toThrow(/optimize-for/);
|
||||
});
|
||||
|
||||
it("raises on missing entry", { timeout: 5000 }, () => {
|
||||
expect(() => parseCliArgs(["--out-dir", "out"])).toThrow(/entry/);
|
||||
});
|
||||
|
||||
it("raises on missing out-dir", { timeout: 5000 }, () => {
|
||||
expect(() => parseCliArgs(["entry.ts"])).toThrow(/out-dir/);
|
||||
});
|
||||
|
||||
it("raises on unknown flag and extra positional", { timeout: 5000 }, () => {
|
||||
expect(() =>
|
||||
parseCliArgs(["x.ts", "--out-dir", "o", "--bogus"])
|
||||
).toThrow(/unknown flag/);
|
||||
expect(() => parseCliArgs(["x.ts", "y.ts", "--out-dir", "o"])).toThrow(
|
||||
/positional/
|
||||
);
|
||||
});
|
||||
|
||||
it("raises when --out-dir is at end without value", {
|
||||
timeout: 5000,
|
||||
}, () => {
|
||||
expect(() => parseCliArgs(["x.ts", "--out-dir"])).toThrow(
|
||||
/requires a value/
|
||||
);
|
||||
});
|
||||
|
||||
it("honours -h and --help", { timeout: 5000 }, () => {
|
||||
expect(parseCliArgs(["-h"]).help).toBe(true);
|
||||
expect(parseCliArgs(["--help"]).help).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe("runCli", () => {
|
||||
it("compiles a fixture and prints a one-line JSON result", {
|
||||
timeout: 120000,
|
||||
}, async () => {
|
||||
const out = mkdtempSync(join(tmpdir(), "cli-ok-"));
|
||||
const stdoutLines: string[] = [];
|
||||
const stderrLines: string[] = [];
|
||||
let exitCode = -1;
|
||||
await runCli([FIXTURE, "--out-dir", out], {
|
||||
stdout: (l) => stdoutLines.push(l),
|
||||
stderr: (l) => stderrLines.push(l),
|
||||
exit: (c) => {
|
||||
exitCode = c;
|
||||
},
|
||||
});
|
||||
expect(exitCode).toBe(0);
|
||||
const parsed = JSON.parse(stdoutLines[0] ?? "{}");
|
||||
expect(parsed.wasmPath.endsWith(".wasm")).toBe(true);
|
||||
expect(parsed.metadataPath.endsWith(".wasm.json")).toBe(true);
|
||||
expect(parsed.routes).toBeGreaterThan(0);
|
||||
rmSync(out, { recursive: true, force: true });
|
||||
});
|
||||
|
||||
it("emits structured error JSON on bad args (exit 2)", {
|
||||
timeout: 5000,
|
||||
}, async () => {
|
||||
const stderrLines: string[] = [];
|
||||
let exitCode = -1;
|
||||
await runCli([], {
|
||||
stdout: () => undefined,
|
||||
stderr: (l) => stderrLines.push(l),
|
||||
exit: (c) => {
|
||||
exitCode = c;
|
||||
},
|
||||
});
|
||||
expect(exitCode).toBe(2);
|
||||
const env = JSON.parse(stderrLines[0] ?? "{}");
|
||||
expect(env.error).toBe("INVALID_ARGS");
|
||||
});
|
||||
|
||||
it("exits 0 on --help", { timeout: 5000 }, async () => {
|
||||
const stdoutLines: string[] = [];
|
||||
let exitCode = -1;
|
||||
await runCli(["--help"], {
|
||||
stdout: (l) => stdoutLines.push(l),
|
||||
stderr: () => undefined,
|
||||
exit: (c) => {
|
||||
exitCode = c;
|
||||
},
|
||||
});
|
||||
expect(exitCode).toBe(0);
|
||||
expect(
|
||||
stdoutLines[0]?.includes("Usage") ||
|
||||
stdoutLines[0]?.includes("suaveplan-wasm-compile")
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it("exits 1 on a compile failure (missing entry file)", {
|
||||
timeout: 30000,
|
||||
}, async () => {
|
||||
const stderrLines: string[] = [];
|
||||
let exitCode = -1;
|
||||
await runCli(["/no/such/file.ts", "--out-dir", "/tmp/x"], {
|
||||
stdout: () => undefined,
|
||||
stderr: (l) => stderrLines.push(l),
|
||||
exit: (c) => {
|
||||
exitCode = c;
|
||||
},
|
||||
});
|
||||
expect(exitCode).toBe(1);
|
||||
const env = JSON.parse(stderrLines[0] ?? "{}");
|
||||
expect(typeof env.code).toBe("string");
|
||||
});
|
||||
|
||||
it("wraps non-WasmCompilerError as WASM_COMPILER.UNCAUGHT", {
|
||||
timeout: 5000,
|
||||
}, async () => {
|
||||
const stderrLines: string[] = [];
|
||||
let exitCode = -1;
|
||||
await runCli([FIXTURE, "--out-dir", "/tmp/cli-uncaught"], {
|
||||
stdout: () => undefined,
|
||||
stderr: (l) => stderrLines.push(l),
|
||||
exit: (c) => {
|
||||
exitCode = c;
|
||||
},
|
||||
compile: async () => {
|
||||
throw new Error("synthetic non-wasm-compiler error");
|
||||
},
|
||||
});
|
||||
expect(exitCode).toBe(1);
|
||||
const env = JSON.parse(stderrLines[0] ?? "{}");
|
||||
expect(env.code).toBe("WASM_COMPILER.UNCAUGHT");
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user