From 822688dc136502f205b4a8fcf5908bac75bc90ce Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sat, 21 Feb 2026 19:42:54 +0000 Subject: [PATCH] test(infra): dedupe store temp fixtures and cover json5 voicewake sanitization --- src/infra/infra-store.test.ts | 87 +++++++++++++++++++++++++++-------- 1 file changed, 67 insertions(+), 20 deletions(-) diff --git a/src/infra/infra-store.test.ts b/src/infra/infra-store.test.ts index 29c8b87d3..0f25a8059 100644 --- a/src/infra/infra-store.test.ts +++ b/src/infra/infra-store.test.ts @@ -20,42 +20,89 @@ import { setVoiceWakeTriggers, } from "./voicewake.js"; +async function withTempDir(prefix: string, run: (dir: string) => Promise) { + const dir = await fs.mkdtemp(path.join(os.tmpdir(), prefix)); + try { + await run(dir); + } finally { + await fs.rm(dir, { recursive: true, force: true }); + } +} + describe("infra store", () => { describe("state migrations fs", () => { it("treats array session stores as invalid", async () => { - const dir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-session-store-")); - const storePath = path.join(dir, "sessions.json"); - await fs.writeFile(storePath, "[]", "utf-8"); + await withTempDir("openclaw-session-store-", async (dir) => { + const storePath = path.join(dir, "sessions.json"); + await fs.writeFile(storePath, "[]", "utf-8"); - const result = readSessionStoreJson5(storePath); - expect(result.ok).toBe(false); - expect(result.store).toEqual({}); + const result = readSessionStoreJson5(storePath); + expect(result.ok).toBe(false); + expect(result.store).toEqual({}); + }); + }); + + it("parses JSON5 object session stores", async () => { + await withTempDir("openclaw-session-store-", async (dir) => { + const storePath = path.join(dir, "sessions.json"); + await fs.writeFile( + storePath, + "{\n // comment allowed in JSON5\n main: { sessionId: 's1', updatedAt: 123 },\n}\n", + "utf-8", + ); + + const result = readSessionStoreJson5(storePath); + expect(result.ok).toBe(true); + expect(result.store.main?.sessionId).toBe("s1"); + expect(result.store.main?.updatedAt).toBe(123); + }); }); }); describe("voicewake store", () => { it("returns defaults when missing", async () => { - const baseDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-voicewake-")); - const cfg = await loadVoiceWakeConfig(baseDir); - expect(cfg.triggers).toEqual(defaultVoiceWakeTriggers()); - expect(cfg.updatedAtMs).toBe(0); + await withTempDir("openclaw-voicewake-", async (baseDir) => { + const cfg = await loadVoiceWakeConfig(baseDir); + expect(cfg.triggers).toEqual(defaultVoiceWakeTriggers()); + expect(cfg.updatedAtMs).toBe(0); + }); }); it("sanitizes and persists triggers", async () => { - const baseDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-voicewake-")); - const saved = await setVoiceWakeTriggers([" hi ", "", " there "], baseDir); - expect(saved.triggers).toEqual(["hi", "there"]); - expect(saved.updatedAtMs).toBeGreaterThan(0); + await withTempDir("openclaw-voicewake-", async (baseDir) => { + const saved = await setVoiceWakeTriggers([" hi ", "", " there "], baseDir); + expect(saved.triggers).toEqual(["hi", "there"]); + expect(saved.updatedAtMs).toBeGreaterThan(0); - const loaded = await loadVoiceWakeConfig(baseDir); - expect(loaded.triggers).toEqual(["hi", "there"]); - expect(loaded.updatedAtMs).toBeGreaterThan(0); + const loaded = await loadVoiceWakeConfig(baseDir); + expect(loaded.triggers).toEqual(["hi", "there"]); + expect(loaded.updatedAtMs).toBeGreaterThan(0); + }); }); it("falls back to defaults when triggers empty", async () => { - const baseDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-voicewake-")); - const saved = await setVoiceWakeTriggers(["", " "], baseDir); - expect(saved.triggers).toEqual(defaultVoiceWakeTriggers()); + await withTempDir("openclaw-voicewake-", async (baseDir) => { + const saved = await setVoiceWakeTriggers(["", " "], baseDir); + expect(saved.triggers).toEqual(defaultVoiceWakeTriggers()); + }); + }); + + it("sanitizes malformed persisted config values", async () => { + await withTempDir("openclaw-voicewake-", async (baseDir) => { + await fs.mkdir(path.join(baseDir, "settings"), { recursive: true }); + await fs.writeFile( + path.join(baseDir, "settings", "voicewake.json"), + JSON.stringify({ + triggers: [" wake ", "", 42, null], + updatedAtMs: -1, + }), + "utf-8", + ); + + const loaded = await loadVoiceWakeConfig(baseDir); + expect(loaded.triggers).toEqual(["wake"]); + expect(loaded.updatedAtMs).toBe(0); + }); }); });