Files
mattpocock-skills-opencode/test/sync.test.ts
T

87 lines
3.4 KiB
TypeScript

import assert from "node:assert/strict"
import { mkdtempSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs"
import { tmpdir } from "node:os"
import path from "node:path"
import { test } from "node:test"
import { diffSnapshots, hashDir, listSkillDirs, recordNewSkills } from "../scripts/sync-upstream.ts"
function fixture() {
const dir = mkdtempSync(path.join(tmpdir(), "sync-test-"))
const skill = (root: string, bucket: string, name: string, body: string, extra?: string) => {
mkdirSync(path.join(root, bucket, name), { recursive: true })
writeFileSync(path.join(root, bucket, name, "SKILL.md"), body)
if (extra) writeFileSync(path.join(root, bucket, name, "EXTRA.md"), extra)
}
return { dir, skill }
}
test("listSkillDirs finds only dirs containing SKILL.md", () => {
const { dir, skill } = fixture()
try {
skill(dir, "engineering", "tdd", "---\nname: tdd\n---\n")
skill(dir, "misc", "wizard", "---\nname: wizard\n---\n")
mkdirSync(path.join(dir, "deprecated"), { recursive: true })
writeFileSync(path.join(dir, "deprecated", "README.md"), "empty bucket")
mkdirSync(path.join(dir, "engineering", "not-a-skill"), { recursive: true })
assert.deepEqual(listSkillDirs(dir), ["engineering/tdd", "misc/wizard"])
assert.deepEqual(listSkillDirs(path.join(dir, "missing")), [])
} finally {
rmSync(dir, { recursive: true, force: true })
}
})
test("diffSnapshots reports added, removed and changed skill dirs", () => {
const { dir, skill } = fixture()
const before = path.join(dir, "before")
const after = path.join(dir, "after")
try {
skill(before, "engineering", "tdd", "v1")
skill(before, "engineering", "gone", "v1")
skill(after, "engineering", "tdd", "v2")
skill(after, "productivity", "fresh", "v1")
assert.deepEqual(diffSnapshots(before, after), {
added: ["productivity/fresh"],
removed: ["engineering/gone"],
changed: ["engineering/tdd"],
})
} finally {
rmSync(dir, { recursive: true, force: true })
}
})
test("hashDir ignores file mtime and is order-independent", () => {
const { dir, skill } = fixture()
const a = path.join(dir, "a")
const b = path.join(dir, "b")
try {
skill(a, "x", "s", "same", "extra")
skill(b, "x", "s", "same", "extra")
assert.equal(hashDir(path.join(a, "x", "s")), hashDir(path.join(b, "x", "s")))
writeFileSync(path.join(b, "x", "s", "EXTRA.md"), "different")
assert.notEqual(hashDir(path.join(a, "x", "s")), hashDir(path.join(b, "x", "s")))
} finally {
rmSync(dir, { recursive: true, force: true })
}
})
test("recordNewSkills appends needs-review entries once and leaves known skills alone", () => {
const { dir } = fixture()
const file = path.join(dir, "classification.json")
try {
writeFileSync(
file,
JSON.stringify({ skills: [{ name: "tdd", bucket: "engineering", status: "analyzed" }] }),
)
const fresh = recordNewSkills(file, ["engineering/tdd", "misc/newcomer"])
assert.deepEqual(fresh, ["newcomer"])
const doc = JSON.parse(readFileSync(file, "utf8"))
assert.equal(doc.skills.length, 2)
assert.equal(doc.skills[1].status, "needs-review")
assert.equal(doc.skills[1].classification, "skill")
// idempotent: second run adds nothing
assert.deepEqual(recordNewSkills(file, ["misc/newcomer"]), [])
} finally {
rmSync(dir, { recursive: true, force: true })
}
})