repositories / dotfiles
dotfiles
bugabingas dorkfiles
owned by admin
pi/agent/skills/writing-skills/scripts/check.test.mjs
Rawimport assert from "node:assert/strict";
import { spawnSync } from "node:child_process";
import {
mkdtempSync,
mkdirSync,
rmSync,
writeFileSync,
} from "node:fs";
import { tmpdir } from "node:os";
import path from "node:path";
import test from "node:test";
import { fileURLToPath } from "node:url";
const skillDir = path.dirname(path.dirname(fileURLToPath(import.meta.url)));
const checker = path.join(skillDir, "scripts", "check.mjs");
const temporaryDirectories = [];
function fixture(name, files) {
const directory = mkdtempSync(path.join(tmpdir(), "writing-skills-check-"));
temporaryDirectories.push(directory);
const root = path.join(directory, name);
mkdirSync(root, { recursive: true });
for (const [relativePath, contents] of Object.entries(files)) {
const file = path.join(root, relativePath);
mkdirSync(path.dirname(file), { recursive: true });
writeFileSync(file, contents);
}
return root;
}
function skill(name = "fixture", body = "") {
return `---\nname: ${name}\ndescription: Fixture skill\n---\n\n# Fixture\n\n${body}`;
}
function check(directory) {
const result = spawnSync(process.execPath, [checker, directory], {
encoding: "utf8",
});
assert.equal(result.error, undefined, result.error?.message);
return {
status: result.status,
output: JSON.parse(result.stdout),
};
}
function codes(output) {
return output.issues.map((issue) => issue.code).sort();
}
test.after(() => {
for (const directory of temporaryDirectories) {
rmSync(directory, { recursive: true, force: true });
}
});
test("minimal prose-only skill needs no package", () => {
const directory = fixture("fixture", { "SKILL.md": skill() });
const result = check(directory);
assert.equal(result.status, 0);
assert.equal(result.output.ok, true);
assert.deepEqual(result.output.issues, []);
});
test("scripted skill requires package and test file", () => {
const directory = fixture("fixture", {
"SKILL.md": skill(),
"scripts/helper.mjs": "// fixture helper; never execute\n",
});
const result = check(directory);
assert.equal(result.status, 1);
assert.equal(result.output.ok, false);
assert.deepEqual(codes(result.output), ["package.missing", "tests.missing"]);
});
test("scripted skill rejects a missing test file", () => {
const directory = fixture("fixture", {
"SKILL.md": skill(),
"package.json": JSON.stringify({ scripts: { test: "node --test" } }),
"scripts/helper.mjs": "// fixture helper; never execute\n",
});
const result = check(directory);
assert.equal(result.status, 1);
assert.deepEqual(codes(result.output), ["tests.missing"]);
});
test("scripted skill accepts direct node test packaging", () => {
const directory = fixture("fixture", {
"SKILL.md": skill(),
"package.json": JSON.stringify({
scripts: { test: "node --test scripts/*.test.mjs" },
}),
"scripts/helper.mjs": "// fixture helper; never execute\n",
"scripts/helper.test.mjs": "// fixture test; never execute\n",
});
const result = check(directory);
assert.equal(result.status, 0);
assert.equal(result.output.ok, true);
});
test("CLI reports usage errors with status 2", () => {
const result = spawnSync(process.execPath, [checker], { encoding: "utf8" });
assert.equal(result.status, 2);
assert.deepEqual(JSON.parse(result.stdout), {
error: "Usage: node scripts/check.mjs <skill-dir>",
});
});
test("owning skill passes its structural self-check", () => {
const result = check(skillDir);
assert.equal(result.status, 0);
assert.equal(result.output.skill, skillDir);
assert.equal(result.output.ok, true);
assert.deepEqual(result.output.issues, []);
});