Files
AgentCompany/tests/unit/skill-format.test.ts
T
2026-04-17 14:03:56 -04:00

180 lines
6.0 KiB
TypeScript

import { describe, it, expect } from "vitest";
import {
parseFrontmatterMarkdown,
classifyInventoryKind,
deriveTrustLevel,
} from "@main/skill-format";
import type { FileInventoryEntry } from "@main/skill-types";
describe("skill-format", () => {
describe("parseFrontmatterMarkdown", () => {
it("parses standard frontmatter and body", () => {
const result = parseFrontmatterMarkdown(
"---\nname: test\nslug: test\n---\n# Body",
);
expect(result.frontmatter).toEqual({ name: "test", slug: "test" });
expect(result.body).toBe("# Body");
});
it("returns empty frontmatter for text without frontmatter", () => {
const result = parseFrontmatterMarkdown("No frontmatter");
expect(result.frontmatter).toEqual({});
expect(result.body).toBe("No frontmatter");
});
it("handles frontmatter with no body", () => {
const result = parseFrontmatterMarkdown("---\nname: test\n---");
expect(result.frontmatter).toEqual({ name: "test" });
expect(result.body).toBe("");
});
it("normalizes CRLF to LF before parsing", () => {
const result = parseFrontmatterMarkdown(
"---\r\nname: test\r\n---\r\n# Body",
);
expect(result.frontmatter).toEqual({ name: "test" });
expect(result.body).toBe("# Body");
});
it("handles quoted string values", () => {
const result = parseFrontmatterMarkdown(
'---\nname: "My Skill"\n---\n',
);
expect(result.frontmatter.name).toBe("My Skill");
});
it("parses boolean values", () => {
const result = parseFrontmatterMarkdown(
"---\nenabled: true\ndisabled: false\n---\n",
);
expect(result.frontmatter.enabled).toBe(true);
expect(result.frontmatter.disabled).toBe(false);
});
it("parses numeric values", () => {
const result = parseFrontmatterMarkdown(
"---\nversion: 42\nprecision: 3.14\n---\n",
);
expect(result.frontmatter.version).toBe(42);
expect(result.frontmatter.precision).toBe(3.14);
});
it("parses null values", () => {
const result = parseFrontmatterMarkdown("---\nvalue: null\n---\n");
expect(result.frontmatter.value).toBeNull();
});
it("handles empty arrays and objects", () => {
const result = parseFrontmatterMarkdown(
"---\nitems: []\nopts: {}\n---\n",
);
expect(result.frontmatter.items).toEqual([]);
expect(result.frontmatter.opts).toEqual({});
});
it("handles body with multiple lines", () => {
const result = parseFrontmatterMarkdown(
"---\nname: test\n---\nLine 1\nLine 2\nLine 3",
);
expect(result.body).toBe("Line 1\nLine 2\nLine 3");
});
});
describe("classifyInventoryKind", () => {
it("classifies SKILL.md as skill", () => {
expect(classifyInventoryKind("SKILL.md")).toBe("skill");
});
it("classifies nested SKILL.md as skill", () => {
expect(classifyInventoryKind("subdir/SKILL.md")).toBe("skill");
});
it("classifies references/ path as reference", () => {
expect(classifyInventoryKind("references/api.md")).toBe("reference");
});
it("classifies scripts/ path as script", () => {
expect(classifyInventoryKind("scripts/build.sh")).toBe("script");
});
it("classifies assets/ path as asset", () => {
expect(classifyInventoryKind("assets/logo.png")).toBe("asset");
});
it("classifies .md files as markdown", () => {
expect(classifyInventoryKind("docs/guide.md")).toBe("markdown");
});
it("classifies config.json as other", () => {
expect(classifyInventoryKind("config.json")).toBe("other");
});
it("classifies .py files as script", () => {
expect(classifyInventoryKind("helper.py")).toBe("script");
});
it("classifies .sh files as script", () => {
expect(classifyInventoryKind("run.sh")).toBe("script");
});
it("classifies .js files as script", () => {
expect(classifyInventoryKind("index.js")).toBe("script");
});
it("classifies .ts files as script", () => {
expect(classifyInventoryKind("main.ts")).toBe("script");
});
it("classifies image files as asset", () => {
expect(classifyInventoryKind("photo.jpg")).toBe("asset");
expect(classifyInventoryKind("icon.svg")).toBe("asset");
expect(classifyInventoryKind("banner.webp")).toBe("asset");
expect(classifyInventoryKind("doc.pdf")).toBe("asset");
});
it("handles case insensitivity", () => {
expect(classifyInventoryKind("Skill.MD")).toBe("skill");
expect(classifyInventoryKind("References/API.md")).toBe("reference");
});
});
describe("deriveTrustLevel", () => {
it("returns scripts_executables when any script file exists", () => {
const inventory: FileInventoryEntry[] = [
{ path: "SKILL.md", kind: "skill" },
{ path: "scripts/build.sh", kind: "script" },
];
expect(deriveTrustLevel(inventory)).toBe("scripts_executables");
});
it("returns assets when asset but no script exists", () => {
const inventory: FileInventoryEntry[] = [
{ path: "SKILL.md", kind: "skill" },
{ path: "assets/logo.png", kind: "asset" },
];
expect(deriveTrustLevel(inventory)).toBe("assets");
});
it("returns assets when other but no script exists", () => {
const inventory: FileInventoryEntry[] = [
{ path: "SKILL.md", kind: "skill" },
{ path: "config.json", kind: "other" },
];
expect(deriveTrustLevel(inventory)).toBe("assets");
});
it("returns markdown_only when only markdown and skill files exist", () => {
const inventory: FileInventoryEntry[] = [
{ path: "SKILL.md", kind: "skill" },
{ path: "references/api.md", kind: "reference" },
{ path: "docs/guide.md", kind: "markdown" },
];
expect(deriveTrustLevel(inventory)).toBe("markdown_only");
});
it("returns markdown_only for empty inventory", () => {
expect(deriveTrustLevel([])).toBe("markdown_only");
});
});
});