Download src/logging/config.test.ts from SaylorTwift/openclaw: direct link, hf CLI and curl.
- Browser
- Download file 7.13 kB
-
https://huggingface.co/SaylorTwift/openclaw/resolve/main/src/logging/config.test.ts
- Command line
-
hf download hf://SaylorTwift/openclaw/src/logging/config.test.ts
-
curl -L -o config.test.ts https://huggingface.co/SaylorTwift/openclaw/resolve/main/src/logging/config.test.ts
7.13 kB
| // Logging config tests cover config file loading and defaults. | |
| import fs from "node:fs"; | |
| import os from "node:os"; | |
| import path from "node:path"; | |
| import { afterEach, describe, expect, it, vi } from "vitest"; | |
| import { withEnv } from "../test-utils/env.js"; | |
| import { readLoggingConfig } from "./config.js"; | |
| import { applyLoggingConfig, resetLogger } from "./logger.js"; | |
| const originalArgv = process.argv; | |
| let tempDirs: string[] = []; | |
| function writeConfig(source: string): string { | |
| const dir = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-logging-config-")); | |
| tempDirs.push(dir); | |
| const configPath = path.join(dir, "openclaw.json"); | |
| fs.writeFileSync(configPath, source); | |
| return configPath; | |
| } | |
| describe("readLoggingConfig", () => { | |
| afterEach(() => { | |
| resetLogger(); | |
| process.argv = originalArgv; | |
| for (const dir of tempDirs) { | |
| fs.rmSync(dir, { force: true, recursive: true }); | |
| } | |
| tempDirs = []; | |
| }); | |
| it("returns the applied runtime snapshot without bootstrap filesystem work", () => { | |
| const existsSync = vi.spyOn(fs, "existsSync"); | |
| applyLoggingConfig({ level: "debug", consoleStyle: "json" }); | |
| expect(readLoggingConfig()).toEqual({ level: "debug", consoleStyle: "json" }); | |
| expect(existsSync).not.toHaveBeenCalled(); | |
| }); | |
| it("reads logging style without a mutating config load for config schema", () => { | |
| process.argv = ["node", "openclaw", "config", "schema"]; | |
| const configPath = writeConfig(`{ logging: { consoleStyle: "json" } }`); | |
| withEnv({ OPENCLAW_CONFIG_PATH: configPath }, () => { | |
| expect(readLoggingConfig()).toStrictEqual({ consoleStyle: "json" }); | |
| }); | |
| }); | |
| it("reads logging config directly from the active config path", () => { | |
| const configPath = writeConfig(`{ | |
| logging: { | |
| level: "debug", | |
| file: "/tmp/openclaw-custom.log", | |
| maxFileBytes: 1234, | |
| }, | |
| }`); | |
| withEnv({ OPENCLAW_CONFIG_PATH: configPath }, () => { | |
| expect(readLoggingConfig()).toStrictEqual({ | |
| level: "debug", | |
| file: "/tmp/openclaw-custom.log", | |
| maxFileBytes: 1234, | |
| }); | |
| }); | |
| }); | |
| it("supports JSON5 comments and trailing commas", () => { | |
| const configPath = writeConfig(`{ | |
| // users commonly keep comments in openclaw.json | |
| logging: { | |
| consoleLevel: "warn", | |
| }, | |
| }`); | |
| withEnv({ OPENCLAW_CONFIG_PATH: configPath }, () => { | |
| expect(readLoggingConfig()).toStrictEqual({ | |
| consoleLevel: "warn", | |
| }); | |
| }); | |
| }); | |
| it("resolves nested includes and environment substitutions for logging style", () => { | |
| const configPath = writeConfig(`{ logging: { $include: "./logging.json5" } }`); | |
| fs.writeFileSync( | |
| path.join(path.dirname(configPath), "logging.json5"), | |
| `{ consoleStyle: "\${OPENCLAW_TEST_CONSOLE_STYLE}", file: "\${MISSING_LOG_FILE}" }`, | |
| ); | |
| withEnv( | |
| { | |
| OPENCLAW_CONFIG_PATH: configPath, | |
| OPENCLAW_TEST_CONSOLE_STYLE: "json", | |
| MISSING_LOG_FILE: undefined, | |
| }, | |
| () => { | |
| expect(readLoggingConfig()).toStrictEqual({ consoleStyle: "json" }); | |
| }, | |
| ); | |
| }); | |
| it("preserves direct logging style when unrelated config resolution fails", () => { | |
| const configPath = writeConfig(`{ | |
| logging: { consoleStyle: "json", file: "\${MISSING_LOG_FILE}" }, | |
| plugins: { $include: "./missing-plugins.json5" }, | |
| models: { providers: { demo: { apiKey: "\${MISSING_DEMO_KEY}" } } }, | |
| }`); | |
| withEnv( | |
| { | |
| OPENCLAW_CONFIG_PATH: configPath, | |
| MISSING_DEMO_KEY: undefined, | |
| MISSING_LOG_FILE: undefined, | |
| }, | |
| () => { | |
| expect(readLoggingConfig()).toStrictEqual({ consoleStyle: "json" }); | |
| }, | |
| ); | |
| }); | |
| it("resolves root-included logging when an unrelated sibling include fails", () => { | |
| const configPath = writeConfig(`{ | |
| $include: "./base.json5", | |
| plugins: { $include: "./missing-plugins.json5" }, | |
| }`); | |
| fs.writeFileSync( | |
| path.join(path.dirname(configPath), "base.json5"), | |
| `{ logging: { consoleStyle: "json", file: "\${MISSING_LOG_FILE}" } }`, | |
| ); | |
| withEnv( | |
| { | |
| OPENCLAW_CONFIG_PATH: configPath, | |
| MISSING_LOG_FILE: undefined, | |
| }, | |
| () => { | |
| expect(readLoggingConfig()).toStrictEqual({ consoleStyle: "json" }); | |
| }, | |
| ); | |
| }); | |
| it("does not cache a partial style while environment-backed fields are unresolved", () => { | |
| const configPath = writeConfig(`{ | |
| logging: { | |
| consoleStyle: "json", | |
| file: "\${OPENCLAW_TEST_LOG_FILE}", | |
| level: "debug", | |
| }, | |
| }`); | |
| withEnv( | |
| { | |
| OPENCLAW_CONFIG_PATH: configPath, | |
| OPENCLAW_TEST_LOG_FILE: undefined, | |
| }, | |
| () => { | |
| expect(readLoggingConfig()).toStrictEqual({ consoleStyle: "json" }); | |
| }, | |
| ); | |
| withEnv( | |
| { | |
| OPENCLAW_CONFIG_PATH: configPath, | |
| OPENCLAW_TEST_LOG_FILE: "/tmp/openclaw-env-backed.log", | |
| }, | |
| () => { | |
| expect(readLoggingConfig()).toStrictEqual({ | |
| consoleStyle: "json", | |
| file: "/tmp/openclaw-env-backed.log", | |
| level: "debug", | |
| }); | |
| }, | |
| ); | |
| }); | |
| it("preserves custom redaction patterns while another logging field is unresolved", () => { | |
| const configPath = writeConfig(`{ | |
| logging: { | |
| consoleStyle: "json", | |
| redactPatterns: ["/custom-only-secret/g"], | |
| file: "\${MISSING_LOG_FILE}", | |
| }, | |
| }`); | |
| withEnv( | |
| { | |
| OPENCLAW_CONFIG_PATH: configPath, | |
| MISSING_LOG_FILE: undefined, | |
| }, | |
| () => { | |
| expect(readLoggingConfig()).toStrictEqual({ | |
| consoleStyle: "json", | |
| redactPatterns: ["/custom-only-secret/g"], | |
| }); | |
| }, | |
| ); | |
| }); | |
| it("returns undefined for missing or malformed config files", () => { | |
| withEnv( | |
| { OPENCLAW_CONFIG_PATH: path.join(os.tmpdir(), "openclaw-missing-config.json") }, | |
| () => { | |
| expect(readLoggingConfig()).toBeUndefined(); | |
| }, | |
| ); | |
| const configPath = writeConfig(`{ logging: `); | |
| withEnv({ OPENCLAW_CONFIG_PATH: configPath }, () => { | |
| expect(readLoggingConfig()).toBeUndefined(); | |
| }); | |
| }); | |
| it("caches a missing config until the path selector changes", () => { | |
| const dir = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-logging-config-missing-")); | |
| tempDirs.push(dir); | |
| const firstPath = path.join(dir, "missing-first.json"); | |
| const secondPath = path.join(dir, "missing-second.json"); | |
| const existsSync = vi.spyOn(fs, "existsSync"); | |
| try { | |
| withEnv({ OPENCLAW_CONFIG_PATH: firstPath }, () => { | |
| expect(readLoggingConfig()).toBeUndefined(); | |
| expect(readLoggingConfig()).toBeUndefined(); | |
| }); | |
| withEnv({ OPENCLAW_CONFIG_PATH: secondPath }, () => { | |
| expect(readLoggingConfig()).toBeUndefined(); | |
| }); | |
| const checksFor = (configPath: string) => | |
| existsSync.mock.calls.filter(([candidate]) => candidate === configPath).length; | |
| expect(checksFor(firstPath)).toBe(1); | |
| expect(checksFor(secondPath)).toBe(1); | |
| } finally { | |
| existsSync.mockRestore(); | |
| } | |
| }); | |
| }); | |