| import { describe, expect, it, test } from "vitest"; |
| import { |
| applyOpenClawManifestInstallCommonFields, |
| getFrontmatterString, |
| normalizeStringList, |
| parseFrontmatterBool, |
| parseOpenClawManifestInstallBase, |
| resolveOpenClawManifestBlock, |
| resolveOpenClawManifestInstall, |
| resolveOpenClawManifestOs, |
| resolveOpenClawManifestRequires, |
| } from "./frontmatter.js"; |
|
|
| describe("shared/frontmatter", () => { |
| test("normalizeStringList handles strings, arrays, and non-list values", () => { |
| expect(normalizeStringList("a, b,,c")).toEqual(["a", "b", "c"]); |
| expect(normalizeStringList([" a ", "", "b", 42])).toEqual(["a", "b", "42"]); |
| expect(normalizeStringList(null)).toEqual([]); |
| }); |
|
|
| test("getFrontmatterString extracts strings only", () => { |
| expect(getFrontmatterString({ a: "b" }, "a")).toBe("b"); |
| expect(getFrontmatterString({ a: 1 }, "a")).toBeUndefined(); |
| }); |
|
|
| test("parseFrontmatterBool respects explicit values and fallback", () => { |
| expect(parseFrontmatterBool("true", false)).toBe(true); |
| expect(parseFrontmatterBool("false", true)).toBe(false); |
| expect(parseFrontmatterBool(undefined, true)).toBe(true); |
| expect(parseFrontmatterBool("maybe", false)).toBe(false); |
| }); |
|
|
| test("resolveOpenClawManifestBlock reads current manifest keys and custom metadata fields", () => { |
| expect( |
| resolveOpenClawManifestBlock({ |
| frontmatter: { |
| metadata: "{ openclaw: { foo: 1, bar: 'baz' } }", |
| }, |
| }), |
| ).toEqual({ foo: 1, bar: "baz" }); |
|
|
| expect( |
| resolveOpenClawManifestBlock({ |
| frontmatter: { |
| pluginMeta: "{ openclaw: { foo: 2 } }", |
| }, |
| key: "pluginMeta", |
| }), |
| ).toEqual({ foo: 2 }); |
| }); |
|
|
| test("resolveOpenClawManifestBlock returns undefined for invalid input", () => { |
| expect(resolveOpenClawManifestBlock({ frontmatter: {} })).toBeUndefined(); |
| expect( |
| resolveOpenClawManifestBlock({ frontmatter: { metadata: "not-json5" } }), |
| ).toBeUndefined(); |
| expect(resolveOpenClawManifestBlock({ frontmatter: { metadata: "123" } })).toBeUndefined(); |
| expect(resolveOpenClawManifestBlock({ frontmatter: { metadata: "[]" } })).toBeUndefined(); |
| expect( |
| resolveOpenClawManifestBlock({ frontmatter: { metadata: "{ nope: { a: 1 } }" } }), |
| ).toBeUndefined(); |
| }); |
|
|
| it("normalizes manifest requirement and os lists", () => { |
| expect( |
| resolveOpenClawManifestRequires({ |
| requires: { |
| bins: "bun, node", |
| anyBins: [" ffmpeg ", ""], |
| env: ["OPENCLAW_TOKEN", " OPENCLAW_URL "], |
| config: null, |
| }, |
| }), |
| ).toEqual({ |
| bins: ["bun", "node"], |
| anyBins: ["ffmpeg"], |
| env: ["OPENCLAW_TOKEN", "OPENCLAW_URL"], |
| config: [], |
| }); |
| expect(resolveOpenClawManifestRequires({})).toBeUndefined(); |
| expect(resolveOpenClawManifestOs({ os: [" darwin ", "linux", ""] })).toEqual([ |
| "darwin", |
| "linux", |
| ]); |
| }); |
|
|
| it("parses and applies install common fields", () => { |
| const parsed = parseOpenClawManifestInstallBase( |
| { |
| type: " Brew ", |
| id: "brew.git", |
| label: "Git", |
| bins: [" git ", "git"], |
| }, |
| ["brew", "npm"], |
| ); |
|
|
| expect(parsed).toEqual({ |
| raw: { |
| type: " Brew ", |
| id: "brew.git", |
| label: "Git", |
| bins: [" git ", "git"], |
| }, |
| kind: "brew", |
| id: "brew.git", |
| label: "Git", |
| bins: ["git", "git"], |
| }); |
| expect(parseOpenClawManifestInstallBase({ kind: "bad" }, ["brew"])).toBeUndefined(); |
| expect( |
| applyOpenClawManifestInstallCommonFields<{ |
| extra: boolean; |
| id?: string; |
| label?: string; |
| bins?: string[]; |
| }>({ extra: true }, parsed!), |
| ).toEqual({ |
| extra: true, |
| id: "brew.git", |
| label: "Git", |
| bins: ["git", "git"], |
| }); |
| }); |
|
|
| it("prefers explicit kind, ignores invalid common fields, and leaves missing ones untouched", () => { |
| const parsed = parseOpenClawManifestInstallBase( |
| { |
| kind: " npm ", |
| type: "brew", |
| id: 42, |
| label: null, |
| bins: [" ", ""], |
| }, |
| ["brew", "npm"], |
| ); |
|
|
| expect(parsed).toEqual({ |
| raw: { |
| kind: " npm ", |
| type: "brew", |
| id: 42, |
| label: null, |
| bins: [" ", ""], |
| }, |
| kind: "npm", |
| }); |
| expect( |
| applyOpenClawManifestInstallCommonFields( |
| { id: "keep", label: "Keep", bins: ["bun"] }, |
| parsed!, |
| ), |
| ).toEqual({ |
| id: "keep", |
| label: "Keep", |
| bins: ["bun"], |
| }); |
| }); |
|
|
| it("maps install entries through the parser and filters rejected specs", () => { |
| expect( |
| resolveOpenClawManifestInstall( |
| { |
| install: [{ id: "keep" }, { id: "drop" }, "bad"], |
| }, |
| (entry) => { |
| if ( |
| typeof entry === "object" && |
| entry !== null && |
| (entry as { id?: string }).id === "keep" |
| ) { |
| return { id: "keep" }; |
| } |
| return undefined; |
| }, |
| ), |
| ).toEqual([{ id: "keep" }]); |
| }); |
| }); |
|
|