import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; import { getResolvedConsoleSettings, getResolvedLoggerSettings, resetLogger, setLoggerOverride, } from "../logging.js"; import { createSuiteLogPathTracker } from "./log-test-helpers.js"; import { loggingState } from "./state.js"; const defaultMaxFileBytes = 500 * 1024 * 1024; const logPathTracker = createSuiteLogPathTracker("openclaw-test-env-log-level-"); describe("OPENCLAW_LOG_LEVEL", () => { let originalEnv: string | undefined; let testLogPath = ""; beforeAll(async () => { await logPathTracker.setup(); }); beforeEach(() => { originalEnv = process.env.OPENCLAW_LOG_LEVEL; testLogPath = logPathTracker.nextPath(); delete process.env.OPENCLAW_LOG_LEVEL; loggingState.invalidEnvLogLevelValue = null; resetLogger(); setLoggerOverride(null); }); afterEach(() => { if (originalEnv === undefined) { delete process.env.OPENCLAW_LOG_LEVEL; } else { process.env.OPENCLAW_LOG_LEVEL = originalEnv; } loggingState.invalidEnvLogLevelValue = null; resetLogger(); setLoggerOverride(null); vi.restoreAllMocks(); }); afterAll(async () => { await logPathTracker.cleanup(); testLogPath = ""; }); it("applies a valid env override to both file and console levels", () => { setLoggerOverride({ level: "error", consoleLevel: "warn", consoleStyle: "json", file: testLogPath, }); process.env.OPENCLAW_LOG_LEVEL = "debug"; expect(getResolvedLoggerSettings()).toEqual({ level: "debug", file: testLogPath, maxFileBytes: defaultMaxFileBytes, }); expect(getResolvedConsoleSettings()).toEqual({ level: "debug", style: "json", }); }); it("warns once and ignores invalid env values", () => { setLoggerOverride({ level: "error", consoleLevel: "warn", consoleStyle: "compact", file: testLogPath, }); process.env.OPENCLAW_LOG_LEVEL = "nope"; const stderrSpy = vi.spyOn(process.stderr, "write").mockImplementation( () => true as unknown as ReturnType, // preserve stream contract in test spy ); expect(getResolvedLoggerSettings().level).toBe("error"); expect(getResolvedLoggerSettings().maxFileBytes).toBe(defaultMaxFileBytes); expect(getResolvedConsoleSettings().level).toBe("warn"); expect(getResolvedLoggerSettings().level).toBe("error"); const warnings = stderrSpy.mock.calls .map(([firstArg]) => String(firstArg)) .filter((line) => line.includes("OPENCLAW_LOG_LEVEL")); expect(warnings).toHaveLength(1); expect(warnings[0]).toContain('Ignoring invalid OPENCLAW_LOG_LEVEL="nope"'); }); });