Files
cycle-atlas/.claude/skills/hyperframes/scripts/plugin-cli.test.mjs
T

121 lines
4.3 KiB
JavaScript
Raw Normal View History

import assert from "node:assert/strict";
import { spawnSync } from "node:child_process";
import {
copyFileSync,
mkdirSync,
mkdtempSync,
readFileSync,
realpathSync,
rmSync,
writeFileSync,
} from "node:fs";
import { join } from "node:path";
import { tmpdir } from "node:os";
import { test } from "node:test";
import { invocation, pluginVersion } from "./plugin-cli.mjs";
function fixture(t, manifest = "plugin.json", version = "1.2.3") {
const root = mkdtempSync(join(tmpdir(), "hf-plugin-"));
t.after(() => rmSync(root, { recursive: true, force: true }));
mkdirSync(join(root, "skills/hyperframes/scripts/lib"), { recursive: true });
mkdirSync(join(root, manifest, ".."), { recursive: true });
writeFileSync(join(root, manifest), JSON.stringify({ name: "hyperframes", version }));
const launcher = join(root, "skills/hyperframes/scripts/plugin-cli.mjs");
copyFileSync(new URL("./plugin-cli.mjs", import.meta.url), launcher);
copyFileSync(
new URL("./lib/main-module.mjs", import.meta.url),
join(root, "skills/hyperframes/scripts/lib/main-module.mjs"),
);
return { root, launcher };
}
for (const manifest of [
"plugin.json",
".claude-plugin/plugin.json",
".codex-plugin/plugin.json",
".cursor-plugin/plugin.json",
"gemini-extension.json",
]) {
test(`locates ${manifest} without repository packages`, (t) => {
const { root } = fixture(t, manifest);
assert.equal(pluginVersion(root), "1.2.3");
});
}
test("rejects missing and floating plugin versions", (t) => {
const { root } = fixture(t, "plugin.json", "latest");
assert.throws(() => pluginVersion(root), /Invalid HyperFrames plugin release/);
rmSync(join(root, "plugin.json"));
assert.throws(() => pluginVersion(root), /No HyperFrames plugin manifest/);
});
test("pins CLI, suppresses standalone refresh, preserves unrelated environment", () => {
const result = invocation(["init", "project with spaces", "--non-interactive"], {
version: "1.2.3",
platform: "darwin",
env: { PATH: "/bin", HYPERFRAMES_SKIP_SKILLS: "0" },
});
assert.equal(result.command, "npx");
assert.deepEqual(result.args, [
"--yes",
"hyperframes@1.2.3",
"init",
"project with spaces",
"--non-interactive",
]);
assert.deepEqual(result.env, {
PATH: "/bin",
HYPERFRAMES_SKIP_SKILLS: "1",
HYPERFRAMES_SKILL_PKG_VERSION: "1.2.3",
HYPERFRAMES_PLUGIN_VERSION: "1.2.3",
HYPERFRAMES_NO_UPDATE_CHECK: "1",
});
assert.throws(() => invocation(["skills", "update"], { version: "1.2.3" }), /plugin manager/);
});
test("Windows launches npx through Node without shell argument interpretation", () => {
const result = invocation(["render", "a & b"], {
version: "1.2.3",
platform: "win32",
node: String.raw`C:\Program Files\nodejs\node.exe`,
env: { npm_execpath: String.raw`C:\Program Files\nodejs\node_modules\npm\bin\npm-cli.js` },
pathExists: (p) => p === String.raw`C:\Program Files\nodejs\node_modules\npm\bin\npx-cli.js`,
});
assert.equal(result.command, String.raw`C:\Program Files\nodejs\node.exe`);
assert.deepEqual(result.args, [
String.raw`C:\Program Files\nodejs\node_modules\npm\bin\npx-cli.js`,
"--yes",
"hyperframes@1.2.3",
"render",
"a & b",
]);
assert.throws(
() => invocation([], { version: "1.2.3", platform: "win32", env: {}, pathExists: () => false }),
/Cannot find npx/,
);
});
test("installed helper keeps cwd, arguments, release environment and exit code", (t) => {
const { root, launcher } = fixture(t);
const project = join(root, "user project");
mkdirSync(project);
const helper = join(root, "helper.mjs");
writeFileSync(
helper,
"console.log(JSON.stringify({ cwd: process.cwd(), args: process.argv.slice(2), skip: process.env.HYPERFRAMES_SKIP_SKILLS, version: process.env.HYPERFRAMES_SKILL_PKG_VERSION })); process.exit(7);",
);
const before = readFileSync(join(root, "plugin.json"), "utf8");
const result = spawnSync(
process.execPath,
[launcher, "--script", helper, "literal $value & spaces"],
{ cwd: project, encoding: "utf8" },
);
assert.equal(result.status, 7, result.stderr);
assert.deepEqual(JSON.parse(result.stdout), {
cwd: realpathSync(project),
args: ["literal $value & spaces"],
skip: "1",
version: "1.2.3",
});
assert.equal(readFileSync(join(root, "plugin.json"), "utf8"), before);
});