import { describe, it, expect, beforeEach, afterEach } from "vitest"; import { mkdtemp, rm, readFile } from "node:fs/promises"; import { tmpdir } from "node:os"; import { join } from "node:path"; import { slugify, artifactRelPath, docRelPath, writeArtifact, type AssetDraft, } from "../src/autoext/artifact-writer.js"; const draft = (over: Partial = {}): AssetDraft => ({ type: "workflow-n8n", name: "Backup Nextcloud", version: "1.0.0", riskTier: "privileged", summary: "Sauvegarde quotidienne.", content: '{"name":"x"}', ...over, }); let root: string; beforeEach(async () => { root = await mkdtemp(join(tmpdir(), "chlova-")); }); afterEach(async () => { await rm(root, { recursive: true, force: true }); }); describe("slugify & chemins", () => { it("slugifie un nom accentué", () => { expect(slugify("Sauvegarde Été #2")).toBe("sauvegarde-ete-2"); }); it("refuse un nom vide", () => { expect(() => slugify(" ")).toThrow(); }); it("chemins par type", () => { expect(artifactRelPath(draft())).toBe("workflows-n8n/backup-nextcloud.v1.0.0.json"); expect(artifactRelPath(draft({ type: "tool" }))).toBe("tools/backup-nextcloud.v1.0.0.json"); expect(docRelPath(draft())).toBe("docs/assets/workflow-n8n-backup-nextcloud.md"); }); }); describe("writeArtifact", () => { it("écrit artefact + doc", async () => { const { artifactPath, docPath } = await writeArtifact(root, draft()); expect(await readFile(join(root, artifactPath), "utf8")).toBe('{"name":"x"}'); const doc = await readFile(join(root, docPath), "utf8"); expect(doc).toContain("Backup Nextcloud"); expect(doc).toContain("v1.0.0"); expect(doc).toContain("bloqué"); // privilégié → bloqué }); it("refuse une version non semver", async () => { await expect(writeArtifact(root, draft({ version: "1.0" }))).rejects.toThrow(/semver/); }); });