import { describe, it, expect } from "vitest"; import type { Manifest } from "../manifest"; import { dispatchTargets, filterTargets, schemaFields, scaffoldInput, isInlineRenderable, allInlineRenderable, } from "../dispatch-form"; const objectSchema = { type: "object", properties: { authorId: { type: "string" }, body: { type: "string" }, flagged: { type: "boolean", default: false }, severity: { type: "string", enum: ["low", "high"] }, }, required: ["authorId", "body"], }; const manifest = { actions: [ { name: "moderation.submit-post", app: "moderation", description: "post", inputSchema: objectSchema, }, { name: "moderation.flag", app: "moderation" }, ], queries: [{ name: "moderation.queue", app: "moderation", projection: "queue" }], } as unknown as Manifest; describe("dispatchTargets", () => { it("reads actions then queries from the flat manifest arrays", () => { const t = dispatchTargets(manifest); expect(t.map((x) => x.name)).toEqual([ "moderation.submit-post", "moderation.flag", "moderation.queue", ]); expect(t[0].kind).toBe("action"); expect(t[2].kind).toBe("query"); expect(t[0].inputSchema).toBe(objectSchema); }); it("is tolerant of a null / partial manifest", () => { expect(dispatchTargets(null)).toEqual([]); expect(dispatchTargets({} as Manifest)).toEqual([]); expect(dispatchTargets({ actions: "nope" } as unknown as Manifest)).toEqual([]); }); it("skips entries without a name", () => { const m = { actions: [{ app: "x" }, { name: "ok", app: "x" }], } as unknown as Manifest; expect(dispatchTargets(m).map((t) => t.name)).toEqual(["ok"]); }); }); describe("filterTargets", () => { const targets = dispatchTargets(manifest); it("returns all on an empty query", () => { expect(filterTargets(targets, " ")).toHaveLength(3); }); it("matches name, app, and description case-insensitively", () => { expect(filterTargets(targets, "FLAG").map((t) => t.name)).toEqual(["moderation.flag"]); expect(filterTargets(targets, "post").map((t) => t.name)).toEqual(["moderation.submit-post"]); expect(filterTargets(targets, "queue").map((t) => t.name)).toEqual(["moderation.queue"]); }); }); describe("schemaFields", () => { it("flattens top-level properties with required/default/enum", () => { const f = schemaFields(objectSchema); expect(f.map((x) => x.name)).toEqual(["authorId", "body", "flagged", "severity"]); expect(f.find((x) => x.name === "authorId")?.required).toBe(true); expect(f.find((x) => x.name === "flagged")?.default).toBe(false); expect(f.find((x) => x.name === "severity")?.enum).toEqual(["low", "high"]); }); it("returns [] for a non-object / schemaless input", () => { expect(schemaFields(undefined)).toEqual([]); expect(schemaFields({ type: "string" })).toEqual([]); }); }); describe("scaffoldInput", () => { it("seeds type-appropriate values and honors defaults", () => { expect(scaffoldInput(objectSchema)).toEqual({ authorId: "", body: "", flagged: false, severity: "", }); }); it("returns {} for a schemaless input", () => { expect(scaffoldInput(null)).toEqual({}); }); }); describe("inline renderability", () => { it("treats primitives as inline-renderable", () => { expect(isInlineRenderable({ name: "a", type: "string", required: true })).toBe(true); expect(isInlineRenderable({ name: "a", type: "object", required: false })).toBe(false); }); it("allInlineRenderable is true only when all fields are primitive", () => { expect(allInlineRenderable(schemaFields(objectSchema))).toBe(true); expect(allInlineRenderable([{ name: "x", type: "object", required: false }])).toBe(false); expect(allInlineRenderable([])).toBe(false); }); });