import { beforeEach, afterEach, describe, expect, it, vi } from "vitest" import { FLAG_DEFAULTS, Flags, getFlags, registerRuntimeFlags, resetFlagsCache, parseBool, } from "@/lib/flags" type FlagName = keyof typeof FLAG_DEFAULTS const flagKeys = Object.keys(FLAG_DEFAULTS) as FlagName[] const originalEnv: Partial> = {} beforeEach(() => { resetFlagsCache() for (const key of flagKeys) { if (!(key in originalEnv)) { originalEnv[key] = process.env[key] } delete process.env[key] } delete (globalThis as Record).__MULTI_AGENT_CHAT_FLAGS__ }) afterEach(() => { resetFlagsCache() for (const key of flagKeys) { const value = originalEnv[key] if (value === undefined) { delete process.env[key] } else { process.env[key] = value } } delete (globalThis as Record).__MULTI_AGENT_CHAT_FLAGS__ }) describe("parseBool", () => { it("handles string coercion and defaults", () => { expect(parseBool("true", false)).toBe(true) expect(parseBool(" FALSE ", true)).toBe(false) expect(parseBool("1", false)).toBe(true) expect(parseBool("0", true)).toBe(false) expect(parseBool(undefined, true)).toBe(true) expect(parseBool(undefined, false)).toBe(false) }) it("handles yes/no values", () => { expect(parseBool("yes", false)).toBe(true) expect(parseBool("YES", false)).toBe(true) expect(parseBool("no", true)).toBe(false) expect(parseBool("NO", true)).toBe(false) }) it("uses default for invalid values", () => { expect(parseBool("invalid", true)).toBe(true) expect(parseBool("maybe", false)).toBe(false) }) }) describe("getFlags", () => { it("returns default values when no environment variables are set", () => { const snapshot = getFlags({ refresh: true }) expect(snapshot).toMatchObject(FLAG_DEFAULTS) expect(snapshot.IMAGE_UPLOADS_ENABLED).toBe(true) expect(snapshot.DIFF_TOOL_ENABLED).toBe(true) }) it("honours environment overrides", () => { process.env.IMAGE_UPLOADS_ENABLED = "false" process.env.DIFF_TOOL_ENABLED = "true" const snapshot = getFlags({ refresh: true }) expect(snapshot.IMAGE_UPLOADS_ENABLED).toBe(false) expect(snapshot.DIFF_TOOL_ENABLED).toBe(true) }) it("caches flags by default", () => { const snapshot1 = getFlags() process.env.IMAGE_UPLOADS_ENABLED = "false" const snapshot2 = getFlags() expect(snapshot2.IMAGE_UPLOADS_ENABLED).toBe(true) // Still cached }) it("refreshes cache when requested", () => { const snapshot1 = getFlags() process.env.IMAGE_UPLOADS_ENABLED = "false" const snapshot2 = getFlags({ refresh: true }) expect(snapshot2.IMAGE_UPLOADS_ENABLED).toBe(false) // Refreshed }) }) describe("registerRuntimeFlags", () => { it("allows runtime overrides to take precedence", () => { process.env.IMAGE_UPLOADS_ENABLED = "true" const override = { IMAGE_UPLOADS_ENABLED: false } registerRuntimeFlags(override) const snapshot = getFlags() expect(snapshot.IMAGE_UPLOADS_ENABLED).toBe(false) }) it("supports partial overrides", () => { registerRuntimeFlags({ DIFF_TOOL_ENABLED: false }) const snapshot = getFlags() expect(snapshot.IMAGE_UPLOADS_ENABLED).toBe(true) // Default expect(snapshot.DIFF_TOOL_ENABLED).toBe(false) // Overridden }) }) describe("Flags proxy", () => { it("reflects current snapshot values", () => { process.env.IMAGE_UPLOADS_ENABLED = "false" const snapshot = getFlags({ refresh: true }) expect(snapshot.IMAGE_UPLOADS_ENABLED).toBe(false) expect(Flags.IMAGE_UPLOADS_ENABLED).toBe(false) }) it("reflects runtime overrides", () => { registerRuntimeFlags({ DIFF_TOOL_ENABLED: false }) expect(Flags.DIFF_TOOL_ENABLED).toBe(false) }) })