106 lines
3.6 KiB
TypeScript
106 lines
3.6 KiB
TypeScript
import assert from "node:assert/strict";
|
|
import { mkdir, mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
|
|
import { tmpdir } from "node:os";
|
|
import { join } from "node:path";
|
|
import test from "node:test";
|
|
import { main, parseWorldArgs } from "../src/cli.ts";
|
|
import { discoverWorlds, resolveWorldScript } from "../src/loader.ts";
|
|
|
|
test("world arguments expose only script lifecycle flags and forward arguments after --", () => {
|
|
assert.deepEqual(
|
|
parseWorldArgs([
|
|
"up",
|
|
"./worlds/dev-headless.ts",
|
|
"--detach",
|
|
"--timeout",
|
|
"5000",
|
|
"--",
|
|
"--replace",
|
|
"value",
|
|
]),
|
|
{
|
|
kind: "up",
|
|
source: "./worlds/dev-headless.ts",
|
|
detach: true,
|
|
timeoutMs: 5000,
|
|
args: ["--replace", "value"],
|
|
},
|
|
);
|
|
|
|
const foregroundTimeout = parseWorldArgs(["up", "dev-headless", "--timeout", "5000"]);
|
|
assert.equal(foregroundTimeout.kind, "help");
|
|
if (foregroundTimeout.kind !== "help") throw new Error("expected help");
|
|
assert.match(foregroundTimeout.error ?? "", /only with --detach/);
|
|
|
|
const oldFlag = parseWorldArgs(["up", "dev-headless", "--keep"]);
|
|
assert.equal(oldFlag.kind, "help");
|
|
if (oldFlag.kind !== "help") throw new Error("expected help");
|
|
assert.match(oldFlag.error ?? "", /Unknown world CLI option "--keep"/);
|
|
|
|
const oldCommand = parseWorldArgs(["resume", "dev-headless"]);
|
|
assert.equal(oldCommand.kind, "help");
|
|
if (oldCommand.kind !== "help") throw new Error("expected help");
|
|
assert.match(oldCommand.error ?? "", /Unknown command "resume"/);
|
|
});
|
|
|
|
test("discovery, resolution, list, and help classify scripts without importing them", async () => {
|
|
const root = await mkdtemp(join(tmpdir(), "openwork-world-cli-discovery-"));
|
|
try {
|
|
const worldsDirectory = join(root, "worlds");
|
|
const fixturePath = join(worldsDirectory, "throwing.ts");
|
|
await mkdir(worldsDirectory);
|
|
await writeFile(fixturePath, 'throw new Error("must not import");\n', "utf8");
|
|
|
|
assert.deepEqual(await discoverWorlds(worldsDirectory), [{
|
|
kind: "script",
|
|
name: "throwing",
|
|
path: fixturePath,
|
|
}]);
|
|
for (const source of ["throwing", "throwing.ts", fixturePath]) {
|
|
assert.deepEqual(await resolveWorldScript(source, { cwd: root, worldsDirectory }), {
|
|
kind: "script",
|
|
name: "throwing",
|
|
path: fixturePath,
|
|
});
|
|
}
|
|
|
|
for (const command of [["list"], ["help"]]) {
|
|
const lines: string[] = [];
|
|
assert.equal(await main(command, {
|
|
cwd: root,
|
|
worldsDirectory,
|
|
print: (line) => lines.push(line),
|
|
}), 0);
|
|
assert.match(lines.join("\n"), /world scripts/i);
|
|
assert.match(lines.join("\n"), /throwing/);
|
|
}
|
|
} finally {
|
|
await rm(root, { recursive: true, force: true });
|
|
}
|
|
});
|
|
|
|
test("foreground scripts receive argv after -- and mirror their exit code", async () => {
|
|
const root = await mkdtemp(join(tmpdir(), "openwork-world-cli-argv-"));
|
|
try {
|
|
const worldsDirectory = join(root, "worlds");
|
|
const outputPath = join(root, "argv.json");
|
|
await mkdir(worldsDirectory);
|
|
await writeFile(join(worldsDirectory, "argv.ts"), `
|
|
import { writeFile } from "node:fs/promises";
|
|
await writeFile(process.argv[2], JSON.stringify(process.argv.slice(3)), "utf8");
|
|
process.exitCode = 7;
|
|
`, "utf8");
|
|
|
|
const code = await main(["up", "argv", "--", outputPath, "--detach", "plain"], {
|
|
cwd: root,
|
|
worldsDirectory,
|
|
print: () => {},
|
|
});
|
|
assert.equal(code, 7);
|
|
const recordedArgs: unknown = JSON.parse(await readFile(outputPath, "utf8"));
|
|
assert.deepEqual(recordedArgs, ["--detach", "plain"]);
|
|
} finally {
|
|
await rm(root, { recursive: true, force: true });
|
|
}
|
|
});
|