import { describe, expect, it } from "vitest"; import { buildConfigChecks, evaluateRequirements, evaluateRequirementsFromMetadata, evaluateRequirementsFromMetadataWithRemote, resolveMissingAnyBins, resolveMissingBins, resolveMissingEnv, resolveMissingOs, } from "./requirements.js"; describe("requirements helpers", () => { it("resolveMissingBins respects local+remote", () => { expect( resolveMissingBins({ required: ["a", "b", "c"], hasLocalBin: (bin) => bin === "a", hasRemoteBin: (bin) => bin === "b", }), ).toEqual(["c"]); }); it("resolveMissingAnyBins requires at least one", () => { expect( resolveMissingAnyBins({ required: [], hasLocalBin: () => false, }), ).toEqual([]); expect( resolveMissingAnyBins({ required: ["a", "b"], hasLocalBin: () => false, hasRemoteAnyBin: () => false, }), ).toEqual(["a", "b"]); expect( resolveMissingAnyBins({ required: ["a", "b"], hasLocalBin: (bin) => bin === "b", }), ).toEqual([]); }); it("resolveMissingOs allows remote platform", () => { expect(resolveMissingOs({ required: [], localPlatform: "linux" })).toEqual([]); expect(resolveMissingOs({ required: ["linux"], localPlatform: "linux" })).toEqual([]); expect( resolveMissingOs({ required: ["darwin"], localPlatform: "linux", remotePlatforms: ["darwin"], }), ).toEqual([]); expect(resolveMissingOs({ required: ["darwin"], localPlatform: "linux" })).toEqual(["darwin"]); }); it("resolveMissingEnv uses predicate", () => { expect( resolveMissingEnv({ required: ["A", "B"], isSatisfied: (name) => name === "B" }), ).toEqual(["A"]); }); it("buildConfigChecks includes status", () => { expect( buildConfigChecks({ required: ["a.b"], isSatisfied: (p) => p === "a.b", }), ).toEqual([{ path: "a.b", satisfied: true }]); }); it("evaluateRequirementsFromMetadata derives required+missing", () => { const res = evaluateRequirementsFromMetadata({ always: false, metadata: { requires: { bins: ["a"], anyBins: ["b"], env: ["E"], config: ["cfg.value"] }, os: ["darwin"], }, hasLocalBin: (bin) => bin === "a", localPlatform: "linux", isEnvSatisfied: (name) => name === "E", isConfigSatisfied: () => false, }); expect(res.required.bins).toEqual(["a"]); expect(res.missing.config).toEqual(["cfg.value"]); expect(res.missing.os).toEqual(["darwin"]); expect(res.eligible).toBe(false); }); it("evaluateRequirements reports config checks and all missing categories directly", () => { const res = evaluateRequirements({ always: false, required: { bins: ["node"], anyBins: ["bun", "deno"], env: ["OPENAI_API_KEY"], config: ["browser.enabled", "gateway.enabled"], os: ["darwin"], }, hasLocalBin: () => false, hasRemoteBin: (bin) => bin === "node", hasRemoteAnyBin: () => false, localPlatform: "linux", remotePlatforms: ["windows"], isEnvSatisfied: () => false, isConfigSatisfied: (path) => path === "gateway.enabled", }); expect(res.missing).toEqual({ bins: [], anyBins: ["bun", "deno"], env: ["OPENAI_API_KEY"], config: ["browser.enabled"], os: ["darwin"], }); expect(res.configChecks).toEqual([ { path: "browser.enabled", satisfied: false }, { path: "gateway.enabled", satisfied: true }, ]); expect(res.eligible).toBe(false); }); it("clears missing requirements when always is true but preserves config checks", () => { const res = evaluateRequirements({ always: true, required: { bins: ["node"], anyBins: ["bun"], env: ["OPENAI_API_KEY"], config: ["browser.enabled"], os: ["darwin"], }, hasLocalBin: () => false, localPlatform: "linux", isEnvSatisfied: () => false, isConfigSatisfied: () => false, }); expect(res.missing).toEqual({ bins: [], anyBins: [], env: [], config: [], os: [] }); expect(res.configChecks).toEqual([{ path: "browser.enabled", satisfied: false }]); expect(res.eligible).toBe(true); }); it("evaluateRequirementsFromMetadataWithRemote wires remote predicates and platforms through", () => { const res = evaluateRequirementsFromMetadataWithRemote({ always: false, metadata: { requires: { bins: ["node"], anyBins: ["bun"], env: ["OPENAI_API_KEY"] }, os: ["darwin"], }, remote: { hasBin: (bin) => bin === "node", hasAnyBin: (bins) => bins.includes("bun"), platforms: ["darwin"], }, hasLocalBin: () => false, localPlatform: "linux", isEnvSatisfied: (name) => name === "OPENAI_API_KEY", isConfigSatisfied: () => true, }); expect(res.required).toEqual({ bins: ["node"], anyBins: ["bun"], env: ["OPENAI_API_KEY"], config: [], os: ["darwin"], }); expect(res.missing).toEqual({ bins: [], anyBins: [], env: [], config: [], os: [] }); expect(res.eligible).toBe(true); }); it("evaluateRequirementsFromMetadata defaults missing metadata to empty requirements", () => { const res = evaluateRequirementsFromMetadata({ always: false, hasLocalBin: () => false, localPlatform: "linux", isEnvSatisfied: () => false, isConfigSatisfied: () => false, }); expect(res.required).toEqual({ bins: [], anyBins: [], env: [], config: [], os: [], }); expect(res.missing).toEqual({ bins: [], anyBins: [], env: [], config: [], os: [], }); expect(res.configChecks).toEqual([]); expect(res.eligible).toBe(true); }); });