d1255b926b
Écrit un asset auto-créé (workflow/outil) + sa doc générée depuis le gabarit, chemins sanitizés (anti-traversée), semver validé. 5 tests (dépôt temp). Le dépôt fait foi avant tout passage en need-review. Palier de risque : reversible (écriture fichier locale, sans commit ni exécution). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
61 lines
1.9 KiB
TypeScript
61 lines
1.9 KiB
TypeScript
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> = {}): 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/);
|
|
});
|
|
});
|