Files
2026-05-30 14:16:04 -05:00

188 lines
6.2 KiB
TypeScript

import { describe, expect, it } from "bun:test"
import { homedir } from "node:os"
import { parseConfig, resolveProjectPath } from "./config.ts"
describe("config", () => {
describe("parseConfig", () => {
it("should return default config for empty input", () => {
const config = parseConfig(undefined)
expect(config.bmPath).toBe("bm")
expect(config.memoryDir).toBe("memory/")
expect(config.memoryFile).toBe("MEMORY.md")
expect(config.autoCapture).toBe(true)
expect(config.captureMinChars).toBe(10)
expect(config.autoRecall).toBe(true)
expect(config.recallPrompt).toContain("Check for active tasks")
expect(config.debug).toBe(false)
expect(config.project).toMatch(/^openclaw-/)
expect(config.projectPath).toBe(".")
})
it("should return default config for null input", () => {
const config = parseConfig(null)
expect(config.memoryDir).toBe("memory/")
})
it("should return default config for non-object input", () => {
expect(parseConfig("string").memoryDir).toBe("memory/")
expect(parseConfig(123).memoryDir).toBe("memory/")
expect(parseConfig([]).memoryDir).toBe("memory/")
})
it("should use provided project name", () => {
const config = parseConfig({ project: "my-custom-project" })
expect(config.project).toBe("my-custom-project")
})
it("should use default project for empty string", () => {
const config = parseConfig({ project: "" })
expect(config.project).toMatch(/^openclaw-/)
})
it("should use provided bmPath", () => {
const config = parseConfig({ bmPath: "/custom/path/to/bm" })
expect(config.bmPath).toBe("/custom/path/to/bm")
})
it("should use provided memoryDir", () => {
const config = parseConfig({ memoryDir: "notes/" })
expect(config.memoryDir).toBe("notes/")
})
it("should support snake_case memory_dir", () => {
const config = parseConfig({ memory_dir: "notes/" })
expect(config.memoryDir).toBe("notes/")
})
it("should use provided memoryFile", () => {
const config = parseConfig({ memoryFile: "MY_MEMORY.md" })
expect(config.memoryFile).toBe("MY_MEMORY.md")
})
it("should support snake_case memory_file", () => {
const config = parseConfig({ memory_file: "MY_MEMORY.md" })
expect(config.memoryFile).toBe("MY_MEMORY.md")
})
it("should use provided projectPath", () => {
const config = parseConfig({ projectPath: "/custom/project/path" })
expect(config.projectPath).toBe("/custom/project/path")
})
it("should default projectPath to workspace root", () => {
const config = parseConfig({ memoryDir: "notes/" })
expect(config.projectPath).toBe(".")
})
it("should use provided autoCapture", () => {
expect(parseConfig({ autoCapture: false }).autoCapture).toBe(false)
expect(parseConfig({ autoCapture: true }).autoCapture).toBe(true)
})
it("should use provided debug flag", () => {
expect(parseConfig({ debug: true }).debug).toBe(true)
expect(parseConfig({ debug: false }).debug).toBe(false)
})
it("should use provided captureMinChars", () => {
expect(parseConfig({ captureMinChars: 25 }).captureMinChars).toBe(25)
expect(parseConfig({ captureMinChars: 0 }).captureMinChars).toBe(0)
})
it("should support snake_case capture_min_chars", () => {
expect(parseConfig({ capture_min_chars: 50 }).captureMinChars).toBe(50)
})
it("should default captureMinChars for non-number input", () => {
expect(parseConfig({ captureMinChars: "abc" }).captureMinChars).toBe(10)
expect(parseConfig({ captureMinChars: -5 }).captureMinChars).toBe(10)
})
it("should use provided autoRecall", () => {
expect(parseConfig({ autoRecall: false }).autoRecall).toBe(false)
expect(parseConfig({ autoRecall: true }).autoRecall).toBe(true)
})
it("should support snake_case auto_recall", () => {
expect(parseConfig({ auto_recall: false }).autoRecall).toBe(false)
})
it("should default autoRecall to true", () => {
expect(parseConfig({}).autoRecall).toBe(true)
})
it("should use provided recallPrompt", () => {
const config = parseConfig({ recallPrompt: "Custom prompt" })
expect(config.recallPrompt).toBe("Custom prompt")
})
it("should support snake_case recall_prompt", () => {
const config = parseConfig({ recall_prompt: "Custom snake" })
expect(config.recallPrompt).toBe("Custom snake")
})
it("should default recallPrompt for empty string", () => {
const config = parseConfig({ recallPrompt: "" })
expect(config.recallPrompt).toContain("Check for active tasks")
})
it("should reject cloud config", () => {
expect(() =>
parseConfig({
cloud: {
url: "https://cloud.basicmemory.com",
api_key: "test-key",
},
}),
).toThrow("basic-memory config has unknown keys: cloud")
})
it("should throw error for unknown config keys", () => {
expect(() => parseConfig({ unknownKey: "value" })).toThrow(
"basic-memory config has unknown keys: unknownKey",
)
})
it("should handle complete config object", () => {
const config = parseConfig({
project: "test-project",
bmPath: "/usr/bin/bm",
memoryDir: "notes/",
memoryFile: "NOTES.md",
projectPath: "/tmp/test-project",
autoCapture: false,
debug: true,
})
expect(config.project).toBe("test-project")
expect(config.memoryDir).toBe("notes/")
expect(config.memoryFile).toBe("NOTES.md")
})
it("should not throw for empty config", () => {
expect(() => parseConfig({})).not.toThrow()
})
})
describe("resolveProjectPath", () => {
it("resolves relative projectPath against workspace", () => {
expect(resolveProjectPath("memory/", "/tmp/workspace")).toBe(
"/tmp/workspace/memory",
)
})
it("expands tilde paths", () => {
expect(resolveProjectPath("~/memory", "/tmp/workspace")).toBe(
`${homedir()}/memory`,
)
})
it("keeps absolute paths unchanged", () => {
expect(resolveProjectPath("/var/data/memory", "/tmp/workspace")).toBe(
"/var/data/memory",
)
})
})
})