From 49b2ec1e2edec221d90d72c93a0ceb3dc209c5ae Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Mon, 20 Apr 2026 21:50:29 +0100 Subject: [PATCH] test(extensions): move config regression coverage --- .../bluebubbles/src/setup-surface.test.ts | 13 ++ extensions/imessage/src/config-schema.test.ts | 43 +++++ extensions/signal/src/config-schema.test.ts | 6 + extensions/telegram/src/config-schema.test.ts | 24 +++ extensions/whatsapp/src/config-schema.test.ts | 66 ++++++++ src/config/config.schema-regressions.test.ts | 158 ------------------ 6 files changed, 152 insertions(+), 158 deletions(-) create mode 100644 extensions/imessage/src/config-schema.test.ts create mode 100644 extensions/whatsapp/src/config-schema.test.ts diff --git a/extensions/bluebubbles/src/setup-surface.test.ts b/extensions/bluebubbles/src/setup-surface.test.ts index 448e609033f..ea0b4ddf9cf 100644 --- a/extensions/bluebubbles/src/setup-surface.test.ts +++ b/extensions/bluebubbles/src/setup-surface.test.ts @@ -449,6 +449,19 @@ describe("BlueBubblesConfigSchema", () => { ).accounts?.work; expect(accountConfig?.enrichGroupParticipantsFromContacts).toBe(true); }); + + it("accepts explicit enrichGroupParticipantsFromContacts at channel and account scope", () => { + const parsed = BlueBubblesConfigSchema.safeParse({ + enrichGroupParticipantsFromContacts: true, + accounts: { + work: { + enrichGroupParticipantsFromContacts: false, + }, + }, + }); + + expect(parsed.success).toBe(true); + }); }); describe("bluebubbles group policy", () => { diff --git a/extensions/imessage/src/config-schema.test.ts b/extensions/imessage/src/config-schema.test.ts new file mode 100644 index 00000000000..8124cd0249d --- /dev/null +++ b/extensions/imessage/src/config-schema.test.ts @@ -0,0 +1,43 @@ +import { describe, expect, it } from "vitest"; +import { IMessageConfigSchema } from "../config-api.js"; + +describe("imessage config schema", () => { + it("accepts safe remoteHost", () => { + const res = IMessageConfigSchema.safeParse({ + remoteHost: "bot@gateway-host", + }); + + expect(res.success).toBe(true); + }); + + it("rejects unsafe remoteHost", () => { + const res = IMessageConfigSchema.safeParse({ + remoteHost: "bot@gateway-host -oProxyCommand=whoami", + }); + + expect(res.success).toBe(false); + if (!res.success) { + expect(res.error.issues[0]?.path.join(".")).toBe("remoteHost"); + } + }); + + it("accepts attachment root patterns", () => { + const res = IMessageConfigSchema.safeParse({ + attachmentRoots: ["/Users/*/Library/Messages/Attachments"], + remoteAttachmentRoots: ["/Volumes/relay/attachments"], + }); + + expect(res.success).toBe(true); + }); + + it("rejects relative attachment roots", () => { + const res = IMessageConfigSchema.safeParse({ + attachmentRoots: ["./attachments"], + }); + + expect(res.success).toBe(false); + if (!res.success) { + expect(res.error.issues[0]?.path.join(".")).toBe("attachmentRoots.0"); + } + }); +}); diff --git a/extensions/signal/src/config-schema.test.ts b/extensions/signal/src/config-schema.test.ts index 393a85cee24..0edfc5f8aa5 100644 --- a/extensions/signal/src/config-schema.test.ts +++ b/extensions/signal/src/config-schema.test.ts @@ -16,6 +16,12 @@ function expectInvalidSignalConfig(config: unknown) { } describe("signal groups schema", () => { + it("accepts accountUuid for loop protection", () => { + expectValidSignalConfig({ + accountUuid: "a1b2c3d4-e5f6-7890-abcd-ef1234567890", + }); + }); + it("accepts top-level group overrides", () => { expectValidSignalConfig({ groups: { diff --git a/extensions/telegram/src/config-schema.test.ts b/extensions/telegram/src/config-schema.test.ts index 456412ac6bf..03ad0316aa8 100644 --- a/extensions/telegram/src/config-schema.test.ts +++ b/extensions/telegram/src/config-schema.test.ts @@ -44,6 +44,21 @@ describe("telegram custom commands schema", () => { }); describe("telegram topic agentId schema", () => { + it("accepts nested groupPolicy overrides", () => { + expectTelegramConfigValid({ + groups: { + "-1001234567890": { + groupPolicy: "open", + topics: { + "42": { + groupPolicy: "disabled", + }, + }, + }, + }, + }); + }); + it("accepts valid agentId in forum group topic config", () => { const res = TelegramConfigSchema.safeParse({ groups: { @@ -237,6 +252,15 @@ describe("telegram token schema", () => { }); describe("telegram poll actions schema", () => { + it("accepts editMessage and createForumTopic actions", () => { + expectTelegramConfigValid({ + actions: { + editMessage: true, + createForumTopic: false, + }, + }); + }); + it("accepts actions.poll", () => { expectTelegramConfigValid({ actions: { poll: false } }); }); diff --git a/extensions/whatsapp/src/config-schema.test.ts b/extensions/whatsapp/src/config-schema.test.ts new file mode 100644 index 00000000000..f18af9f7ce5 --- /dev/null +++ b/extensions/whatsapp/src/config-schema.test.ts @@ -0,0 +1,66 @@ +import { describe, expect, it } from "vitest"; +import { WhatsAppConfigSchema } from "../config-api.js"; + +function expectWhatsAppConfigValid(config: unknown) { + const res = WhatsAppConfigSchema.safeParse(config); + expect(res.success).toBe(true); + return res; +} + +describe("whatsapp config schema", () => { + it("accepts enabled", () => { + expectWhatsAppConfigValid({ + enabled: true, + }); + }); + + it("keeps inherited account defaults unset at account scope", () => { + const res = expectWhatsAppConfigValid({ + dmPolicy: "allowlist", + groupPolicy: "open", + debounceMs: 250, + allowFrom: ["+15550001111"], + accounts: { + work: { + allowFrom: ["+15550002222"], + }, + }, + }); + + if (!res.success) { + return; + } + expect(res.data.dmPolicy).toBe("allowlist"); + expect(res.data.groupPolicy).toBe("open"); + expect(res.data.debounceMs).toBe(250); + expect(res.data.accounts?.work?.dmPolicy).toBeUndefined(); + expect(res.data.accounts?.work?.groupPolicy).toBeUndefined(); + expect(res.data.accounts?.work?.debounceMs).toBeUndefined(); + }); + + it("accepts allowlist accounts inheriting allowFrom from accounts.default", () => { + expectWhatsAppConfigValid({ + accounts: { + default: { + allowFrom: ["+15550001111"], + }, + work: { + dmPolicy: "allowlist", + }, + }, + }); + }); + + it("accepts allowlist accounts inheriting allowFrom from mixed-case accounts.Default", () => { + expectWhatsAppConfigValid({ + accounts: { + Default: { + allowFrom: ["+15550001111"], + }, + work: { + dmPolicy: "allowlist", + }, + }, + }); + }); +}); diff --git a/src/config/config.schema-regressions.test.ts b/src/config/config.schema-regressions.test.ts index bf2449e1021..c7738ba6e35 100644 --- a/src/config/config.schema-regressions.test.ts +++ b/src/config/config.schema-regressions.test.ts @@ -1,126 +1,7 @@ import { describe, expect, it } from "vitest"; import { validateConfigObject } from "./validation.js"; -import { - BlueBubblesConfigSchema, - IMessageConfigSchema, - SignalConfigSchema, - TelegramConfigSchema, -} from "./zod-schema.providers-core.js"; -import { WhatsAppConfigSchema } from "./zod-schema.providers-whatsapp.js"; describe("config schema regressions", () => { - it("accepts nested telegram groupPolicy overrides", () => { - const res = TelegramConfigSchema.safeParse({ - groups: { - "-1001234567890": { - groupPolicy: "open", - topics: { - "42": { - groupPolicy: "disabled", - }, - }, - }, - }, - }); - - expect(res.success).toBe(true); - }); - - it("accepts telegram actions editMessage and createForumTopic", () => { - const res = TelegramConfigSchema.safeParse({ - actions: { - editMessage: true, - createForumTopic: false, - }, - }); - - expect(res.success).toBe(true); - }); - - it("accepts channels.whatsapp.enabled", () => { - const res = WhatsAppConfigSchema.safeParse({ - enabled: true, - }); - - expect(res.success).toBe(true); - }); - - it("keeps inherited WhatsApp account defaults unset at account scope", () => { - const res = WhatsAppConfigSchema.safeParse({ - dmPolicy: "allowlist", - groupPolicy: "open", - debounceMs: 250, - allowFrom: ["+15550001111"], - accounts: { - work: { - allowFrom: ["+15550002222"], - }, - }, - }); - - expect(res.success).toBe(true); - if (!res.success) { - return; - } - expect(res.data.dmPolicy).toBe("allowlist"); - expect(res.data.groupPolicy).toBe("open"); - expect(res.data.debounceMs).toBe(250); - expect(res.data.accounts?.work?.dmPolicy).toBeUndefined(); - expect(res.data.accounts?.work?.groupPolicy).toBeUndefined(); - expect(res.data.accounts?.work?.debounceMs).toBeUndefined(); - }); - - it("accepts WhatsApp allowlist accounts inheriting allowFrom from accounts.default", () => { - const res = WhatsAppConfigSchema.safeParse({ - accounts: { - default: { - allowFrom: ["+15550001111"], - }, - work: { - dmPolicy: "allowlist", - }, - }, - }); - - expect(res.success).toBe(true); - }); - - it("accepts WhatsApp allowlist accounts inheriting allowFrom from mixed-case accounts.Default", () => { - const res = WhatsAppConfigSchema.safeParse({ - accounts: { - Default: { - allowFrom: ["+15550001111"], - }, - work: { - dmPolicy: "allowlist", - }, - }, - }); - - expect(res.success).toBe(true); - }); - - it("accepts signal accountUuid for loop protection", () => { - const res = SignalConfigSchema.safeParse({ - accountUuid: "a1b2c3d4-e5f6-7890-abcd-ef1234567890", - }); - - expect(res.success).toBe(true); - }); - - it("accepts BlueBubbles enrichGroupParticipantsFromContacts at channel and account scope", () => { - const res = BlueBubblesConfigSchema.safeParse({ - enrichGroupParticipantsFromContacts: true, - accounts: { - work: { - enrichGroupParticipantsFromContacts: false, - }, - }, - }); - - expect(res.success).toBe(true); - }); - it('accepts memorySearch fallback "voyage"', () => { const res = validateConfigObject({ agents: { @@ -264,34 +145,6 @@ describe("config schema regressions", () => { expect(res.ok).toBe(true); }); - it("accepts safe iMessage remoteHost", () => { - const res = IMessageConfigSchema.safeParse({ - remoteHost: "bot@gateway-host", - }); - - expect(res.success).toBe(true); - }); - - it("rejects unsafe iMessage remoteHost", () => { - const res = IMessageConfigSchema.safeParse({ - remoteHost: "bot@gateway-host -oProxyCommand=whoami", - }); - - expect(res.success).toBe(false); - if (!res.success) { - expect(res.error.issues[0]?.path.join(".")).toBe("remoteHost"); - } - }); - - it("accepts iMessage attachment root patterns", () => { - const res = IMessageConfigSchema.safeParse({ - attachmentRoots: ["/Users/*/Library/Messages/Attachments"], - remoteAttachmentRoots: ["/Volumes/relay/attachments"], - }); - - expect(res.success).toBe(true); - }); - it("accepts string values for agents defaults model inputs", () => { const res = validateConfigObject({ agents: { @@ -339,17 +192,6 @@ describe("config schema regressions", () => { } }); - it("rejects relative iMessage attachment roots", () => { - const res = IMessageConfigSchema.safeParse({ - attachmentRoots: ["./attachments"], - }); - - expect(res.success).toBe(false); - if (!res.success) { - expect(res.error.issues[0]?.path.join(".")).toBe("attachmentRoots.0"); - } - }); - it("accepts browser.extraArgs for proxy and custom flags", () => { const res = validateConfigObject({ browser: {