From e8ad80afc72ac1db50b8655314ab8972ea9283fa Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sun, 8 Mar 2026 14:53:03 +0000 Subject: [PATCH] test: cover invalid talk config inputs --- src/config/config.talk-validation.test.ts | 40 +++++++++++++++++++++++ src/config/zod-schema.talk.test.ts | 28 ++++++++++++++++ 2 files changed, 68 insertions(+) create mode 100644 src/config/config.talk-validation.test.ts create mode 100644 src/config/zod-schema.talk.test.ts diff --git a/src/config/config.talk-validation.test.ts b/src/config/config.talk-validation.test.ts new file mode 100644 index 00000000000..8a0c93ecd3b --- /dev/null +++ b/src/config/config.talk-validation.test.ts @@ -0,0 +1,40 @@ +import { beforeEach, describe, expect, it, vi } from "vitest"; +import { clearConfigCache, loadConfig } from "./config.js"; +import { withTempHomeConfig } from "./test-helpers.js"; + +describe("talk config validation fail-closed behavior", () => { + beforeEach(() => { + clearConfigCache(); + vi.restoreAllMocks(); + }); + + it.each([ + ["boolean", true], + ["string", "1500"], + ["float", 1500.5], + ])("rejects %s talk.silenceTimeoutMs during config load", async (_label, value) => { + await withTempHomeConfig( + { + agents: { list: [{ id: "main" }] }, + talk: { + silenceTimeoutMs: value, + }, + }, + async () => { + const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => {}); + + let thrown: unknown; + try { + loadConfig(); + } catch (error) { + thrown = error; + } + + expect(thrown).toBeInstanceOf(Error); + expect((thrown as { code?: string } | undefined)?.code).toBe("INVALID_CONFIG"); + expect((thrown as Error).message).toMatch(/silenceTimeoutMs|talk/i); + expect(consoleSpy).toHaveBeenCalled(); + }, + ); + }); +}); diff --git a/src/config/zod-schema.talk.test.ts b/src/config/zod-schema.talk.test.ts new file mode 100644 index 00000000000..6f1f22ebc14 --- /dev/null +++ b/src/config/zod-schema.talk.test.ts @@ -0,0 +1,28 @@ +import { describe, expect, it } from "vitest"; +import { OpenClawSchema } from "./zod-schema.js"; + +describe("OpenClawSchema talk validation", () => { + it("accepts a positive integer talk.silenceTimeoutMs", () => { + expect(() => + OpenClawSchema.parse({ + talk: { + silenceTimeoutMs: 1500, + }, + }), + ).not.toThrow(); + }); + + it.each([ + ["boolean", true], + ["string", "1500"], + ["float", 1500.5], + ])("rejects %s talk.silenceTimeoutMs", (_label, value) => { + expect(() => + OpenClawSchema.parse({ + talk: { + silenceTimeoutMs: value, + }, + }), + ).toThrow(/silenceTimeoutMs|number|integer/i); + }); +});