diff --git a/src/shared/config-eval.test.ts b/src/shared/config-eval.test.ts index 2ef18d1bef6..48ddb9e3298 100644 --- a/src/shared/config-eval.test.ts +++ b/src/shared/config-eval.test.ts @@ -1,5 +1,98 @@ import { describe, expect, it } from "vitest"; -import { evaluateRuntimeEligibility } from "./config-eval.js"; +import { + evaluateRuntimeEligibility, + evaluateRuntimeRequires, + isConfigPathTruthyWithDefaults, + isTruthy, + resolveConfigPath, +} from "./config-eval.js"; + +describe("config-eval helpers", () => { + it("normalizes truthy values across primitive types", () => { + expect(isTruthy(undefined)).toBe(false); + expect(isTruthy(null)).toBe(false); + expect(isTruthy(false)).toBe(false); + expect(isTruthy(true)).toBe(true); + expect(isTruthy(0)).toBe(false); + expect(isTruthy(1)).toBe(true); + expect(isTruthy(" ")).toBe(false); + expect(isTruthy(" ok ")).toBe(true); + expect(isTruthy({})).toBe(true); + }); + + it("resolves nested config paths and missing branches safely", () => { + const config = { + browser: { + enabled: true, + nested: { + count: 1, + }, + }, + }; + + expect(resolveConfigPath(config, "browser.enabled")).toBe(true); + expect(resolveConfigPath(config, ".browser..nested.count.")).toBe(1); + expect(resolveConfigPath(config, "browser.missing.value")).toBeUndefined(); + expect(resolveConfigPath("not-an-object", "browser.enabled")).toBeUndefined(); + }); + + it("uses defaults only when config paths are unresolved", () => { + const config = { + browser: { + enabled: false, + }, + }; + + expect( + isConfigPathTruthyWithDefaults(config, "browser.enabled", { "browser.enabled": true }), + ).toBe(false); + expect( + isConfigPathTruthyWithDefaults(config, "browser.missing", { "browser.missing": true }), + ).toBe(true); + expect(isConfigPathTruthyWithDefaults(config, "browser.other", {})).toBe(false); + }); +}); + +describe("evaluateRuntimeRequires", () => { + it("accepts remote bins and remote any-bin matches", () => { + const result = evaluateRuntimeRequires({ + requires: { + bins: ["node"], + anyBins: ["bun", "deno"], + env: ["OPENAI_API_KEY"], + config: ["browser.enabled"], + }, + hasBin: () => false, + hasRemoteBin: (bin) => bin === "node", + hasAnyRemoteBin: (bins) => bins.includes("deno"), + hasEnv: (name) => name === "OPENAI_API_KEY", + isConfigPathTruthy: (path) => path === "browser.enabled", + }); + + expect(result).toBe(true); + }); + + it("rejects when any required runtime check is still unsatisfied", () => { + expect( + evaluateRuntimeRequires({ + requires: { bins: ["node"] }, + hasBin: () => false, + hasEnv: () => true, + isConfigPathTruthy: () => true, + }), + ).toBe(false); + + expect( + evaluateRuntimeRequires({ + requires: { anyBins: ["bun", "node"] }, + hasBin: () => false, + hasAnyRemoteBin: () => false, + hasEnv: () => true, + isConfigPathTruthy: () => true, + }), + ).toBe(false); + }); +}); describe("evaluateRuntimeEligibility", () => { it("rejects entries when required OS does not match local or remote", () => {