/* Unit tests for actionspbt — actions.pbt covering its documented public contract and regression-sensitive edge cases. Not a contract source of truth — the module under test owns the authoritative behavior; fixtures are minimal scaffolding only. RFC-0347: initial PBT illustrative example for agent-gate validation invariants. */ import { test, expect } from "vitest"; import fc from "fast-check"; import { validateAgainstCapabilitySchema } from "../actions.ts"; import type { CapabilityInputOutputSchema } from "@warpgogol/werkstatt-shared/ontology"; const stringSchema: CapabilityInputOutputSchema = { type: "object", additionalProperties: false, properties: { name: { type: "string", minLength: 1, maxLength: 100 }, email: { type: "string", format: "email" }, }, required: ["name"], }; test("PBT: non-object input (string) always fails validation", () => { fc.assert( fc.property(fc.string({ minLength: 1 }), (s) => { const result = validateAgainstCapabilitySchema(stringSchema, s); expect(result.ok).toBe(false); }), ); }); test("PBT: non-object input (number) always fails validation", () => { fc.assert( fc.property(fc.nat(), (n) => { const result = validateAgainstCapabilitySchema(stringSchema, n); expect(result.ok).toBe(false); }), ); }); test("PBT: non-object input (array) always fails validation", () => { fc.assert( fc.property(fc.array(fc.string()), (arr) => { const result = validateAgainstCapabilitySchema(stringSchema, arr); expect(result.ok).toBe(false); }), ); }); test("PBT: object with unknown property always reports an error for that property", () => { fc.assert( fc.property( fc.string({ minLength: 1 }).filter((s) => s !== "name" && s !== "email"), (unknownKey) => { const result = validateAgainstCapabilitySchema(stringSchema, { [unknownKey]: "value" }); expect(result.ok).toBe(false); if (!result.ok) { expect(result.errors.some((e) => e.path === unknownKey)).toBe(true); } }, ), ); }); test("PBT: object missing required 'name' always reports 'name' as required", () => { fc.assert( fc.property(fc.option(fc.string({ maxLength: 50 })), (email) => { const input: Record = {}; if (email !== null) input.email = email; const result = validateAgainstCapabilitySchema(stringSchema, input); expect(result.ok).toBe(false); if (!result.ok) { expect(result.errors.some((e) => e.path === "name")).toBe(true); } }), ); });