From a0b9ce31bd3deba17e3783233bfca3aac7628f51 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sat, 14 Feb 2026 23:57:45 +0000 Subject: [PATCH] perf(test): streamline imessage monitor suites --- ...essages-without-mention-by-default.test.ts | 398 ++++++++---------- src/imessage/monitor.test-harness.ts | 8 + 2 files changed, 173 insertions(+), 233 deletions(-) diff --git a/src/imessage/monitor.skips-group-messages-without-mention-by-default.test.ts b/src/imessage/monitor.skips-group-messages-without-mention-by-default.test.ts index 2474c22e0..f9d1ecf50 100644 --- a/src/imessage/monitor.skips-group-messages-without-mention-by-default.test.ts +++ b/src/imessage/monitor.skips-group-messages-without-mention-by-default.test.ts @@ -60,7 +60,7 @@ async function closeMonitor() { } describe("monitorIMessageProvider", () => { - it("ignores malformed rpc message payloads", async () => { + it("handles default config gating, formatting, and reply context", async () => { const run = startMonitor(); await waitForSubscribe(); @@ -69,39 +69,104 @@ describe("monitorIMessageProvider", () => { sender: { nested: "not-a-string" }, text: "hello", }); - await flush(); - await closeMonitor(); - await run; - expect(replyMock).not.toHaveBeenCalled(); expect(sendMock).not.toHaveBeenCalled(); - }); + replyMock.mockClear(); + sendMock.mockClear(); - it("skips group messages without a mention by default", async () => { - const run = startMonitor(); - await waitForSubscribe(); - - getNotificationHandler()?.({ - method: "message", - params: { - message: { - id: 1, - chat_id: 99, - sender: "+15550001111", - is_from_me: false, - text: "hello group", - is_group: true, - }, - }, + notifyMessage({ + id: 2, + chat_id: 99, + sender: "+15550001111", + is_from_me: false, + text: "hello group", + is_group: true, }); - await flush(); - await closeMonitor(); - await run; - expect(replyMock).not.toHaveBeenCalled(); expect(sendMock).not.toHaveBeenCalled(); + replyMock.mockClear(); + sendMock.mockClear(); + + replyMock.mockResolvedValueOnce({ text: "yo" }); + notifyMessage({ + id: 3, + chat_id: 42, + sender: "+15550002222", + is_from_me: false, + text: "@openclaw ping", + is_group: true, + chat_name: "Lobster Squad", + participants: ["+1555", "+1556"], + }); + await flush(); + expect(replyMock).toHaveBeenCalledOnce(); + { + const ctx = replyMock.mock.calls[0]?.[0] as { Body?: string; ChatType?: string }; + expect(ctx.ChatType).toBe("group"); + // Sender should appear as prefix in group messages (no redundant [from:] suffix) + expect(String(ctx.Body ?? "")).toContain("+15550002222:"); + expect(String(ctx.Body ?? "")).not.toContain("[from:"); + } + expect(sendMock).toHaveBeenCalledWith( + "chat_id:42", + "yo", + expect.objectContaining({ client: expect.any(Object) }), + ); + replyMock.mockClear(); + sendMock.mockClear(); + + notifyMessage({ + id: 4, + chat_id: 99, + chat_name: "Test Group", + sender: "+15550001111", + is_from_me: false, + text: "@openclaw hi", + is_group: true, + created_at: "2026-01-17T00:00:00Z", + }); + await flush(); + expect(replyMock).toHaveBeenCalled(); + { + const ctx = replyMock.mock.calls[0]?.[0]; + const body = ctx?.Body ?? ""; + expect(body).toContain("Test Group id:99"); + expect(body).toContain("+15550001111: @openclaw hi"); + } + replyMock.mockClear(); + sendMock.mockClear(); + + notifyMessage({ + id: 5, + chat_id: 55, + sender: "+15550001111", + is_from_me: false, + text: "replying now", + is_group: false, + reply_to_id: 9001, + reply_to_text: "original message", + reply_to_sender: "+15559998888", + }); + await flush(); + expect(replyMock).toHaveBeenCalled(); + { + const ctx = replyMock.mock.calls[0]?.[0] as { + Body?: string; + ReplyToId?: string; + ReplyToBody?: string; + ReplyToSender?: string; + }; + expect(ctx.ReplyToId).toBe("9001"); + expect(ctx.ReplyToBody).toBe("original message"); + expect(ctx.ReplyToSender).toBe("+15559998888"); + expect(String(ctx.Body ?? "")).toContain("[Replying to +15559998888 id:9001]"); + expect(String(ctx.Body ?? "")).toContain("original message"); + } + + await closeMonitor(); + await run; }); it("allows group messages when imessage groups default disables mention gating", async () => { @@ -117,21 +182,17 @@ describe("monitorIMessageProvider", () => { }, }, }); + const run = startMonitor(); await waitForSubscribe(); - getNotificationHandler()?.({ - method: "message", - params: { - message: { - id: 11, - chat_id: 123, - sender: "+15550001111", - is_from_me: false, - text: "hello group", - is_group: true, - }, - }, + notifyMessage({ + id: 11, + chat_id: 123, + sender: "+15550001111", + is_from_me: false, + text: "hello group", + is_group: true, }); await flush(); @@ -145,7 +206,10 @@ describe("monitorIMessageProvider", () => { const config = getConfig(); setConfigMock({ ...config, - messages: { groupChat: { mentionPatterns: [] } }, + messages: { + ...config.messages, + groupChat: { mentionPatterns: [] }, + }, channels: { ...config.channels, imessage: { @@ -155,21 +219,17 @@ describe("monitorIMessageProvider", () => { }, }, }); + const run = startMonitor(); await waitForSubscribe(); - getNotificationHandler()?.({ - method: "message", - params: { - message: { - id: 12, - chat_id: 777, - sender: "+15550001111", - is_from_me: false, - text: "hello group", - is_group: true, - }, - }, + notifyMessage({ + id: 12, + chat_id: 777, + sender: "+15550001111", + is_from_me: false, + text: "hello group", + is_group: true, }); await flush(); @@ -191,21 +251,17 @@ describe("monitorIMessageProvider", () => { }, }, }); + const run = startMonitor(); await waitForSubscribe(); - getNotificationHandler()?.({ - method: "message", - params: { - message: { - id: 13, - chat_id: 123, - sender: "+15550001111", - is_from_me: false, - text: "@openclaw hello", - is_group: true, - }, - }, + notifyMessage({ + id: 13, + chat_id: 123, + sender: "+15550001111", + is_from_me: false, + text: "@openclaw hello", + is_group: true, }); await flush(); @@ -234,18 +290,13 @@ describe("monitorIMessageProvider", () => { const run = startMonitor(); await waitForSubscribe(); - getNotificationHandler()?.({ - method: "message", - params: { - message: { - id: 14, - chat_id: 2, - sender: "+15550001111", - is_from_me: false, - text: "hello", - is_group: false, - }, - }, + notifyMessage({ + id: 14, + chat_id: 2, + sender: "+15550001111", + is_from_me: false, + text: "hello", + is_group: false, }); await flush(); @@ -265,24 +316,23 @@ describe("monitorIMessageProvider", () => { const config = getConfig(); setConfigMock({ ...config, - messages: { responsePrefix: "PFX" }, + messages: { + ...config.messages, + responsePrefix: "PFX", + }, }); replyMock.mockResolvedValue({ text: "final reply" }); + const run = startMonitor(); await waitForSubscribe(); - getNotificationHandler()?.({ - method: "message", - params: { - message: { - id: 7, - chat_id: 77, - sender: "+15550001111", - is_from_me: false, - text: "hello", - is_group: false, - }, - }, + notifyMessage({ + id: 7, + chat_id: 77, + sender: "+15550001111", + is_from_me: false, + text: "hello", + is_group: false, }); await flush(); @@ -307,21 +357,17 @@ describe("monitorIMessageProvider", () => { }, }, }); + const run = startMonitor(); await waitForSubscribe(); - getNotificationHandler()?.({ - method: "message", - params: { - message: { - id: 99, - chat_id: 77, - sender: "+15550001111", - is_from_me: false, - text: "hello", - is_group: false, - }, - }, + notifyMessage({ + id: 99, + chat_id: 77, + sender: "+15550001111", + is_from_me: false, + text: "hello", + is_group: false, }); await flush(); @@ -337,45 +383,6 @@ describe("monitorIMessageProvider", () => { expect(String(sendMock.mock.calls[0]?.[1] ?? "")).toContain("Pairing code: PAIRCODE"); }); - it("delivers group replies when mentioned", async () => { - replyMock.mockResolvedValueOnce({ text: "yo" }); - const run = startMonitor(); - await waitForSubscribe(); - - getNotificationHandler()?.({ - method: "message", - params: { - message: { - id: 2, - chat_id: 42, - sender: "+15550002222", - is_from_me: false, - text: "@openclaw ping", - is_group: true, - chat_name: "Lobster Squad", - participants: ["+1555", "+1556"], - }, - }, - }); - - await flush(); - await closeMonitor(); - await run; - - expect(replyMock).toHaveBeenCalledOnce(); - const ctx = replyMock.mock.calls[0]?.[0] as { Body?: string; ChatType?: string }; - expect(ctx.ChatType).toBe("group"); - // Sender should appear as prefix in group messages (no redundant [from:] suffix) - expect(String(ctx.Body ?? "")).toContain("+15550002222:"); - expect(String(ctx.Body ?? "")).not.toContain("[from:"); - - expect(sendMock).toHaveBeenCalledWith( - "chat_id:42", - "yo", - expect.objectContaining({ client: expect.any(Object) }), - ); - }); - it("honors group allowlist when groupPolicy is allowlist", async () => { const config = getConfig(); setConfigMock({ @@ -389,21 +396,17 @@ describe("monitorIMessageProvider", () => { }, }, }); + const run = startMonitor(); await waitForSubscribe(); - getNotificationHandler()?.({ - method: "message", - params: { - message: { - id: 3, - chat_id: 202, - sender: "+15550003333", - is_from_me: false, - text: "@openclaw hi", - is_group: true, - }, - }, + notifyMessage({ + id: 3, + chat_id: 202, + sender: "+15550003333", + is_from_me: false, + text: "@openclaw hi", + is_group: true, }); await flush(); @@ -430,6 +433,7 @@ describe("monitorIMessageProvider", () => { }, }); readAllowFromStoreMock.mockResolvedValue(["+15550003333"]); + const run = startMonitor(); await waitForSubscribe(); @@ -466,6 +470,7 @@ describe("monitorIMessageProvider", () => { }, }); readAllowFromStoreMock.mockResolvedValue(["+15550003333"]); + const run = startMonitor(); await waitForSubscribe(); @@ -502,6 +507,7 @@ describe("monitorIMessageProvider", () => { }, }); readAllowFromStoreMock.mockResolvedValue(["+15550003333"]); + const run = startMonitor(); await waitForSubscribe(); @@ -534,21 +540,17 @@ describe("monitorIMessageProvider", () => { }, }, }); + const run = startMonitor(); await waitForSubscribe(); - getNotificationHandler()?.({ - method: "message", - params: { - message: { - id: 10, - chat_id: 303, - sender: "+15550003333", - is_from_me: false, - text: "@openclaw hi", - is_group: true, - }, - }, + notifyMessage({ + id: 10, + chat_id: 303, + sender: "+15550003333", + is_from_me: false, + text: "@openclaw hi", + is_group: true, }); await flush(); @@ -557,74 +559,4 @@ describe("monitorIMessageProvider", () => { expect(replyMock).not.toHaveBeenCalled(); }); - - it("prefixes group message bodies with sender", async () => { - const run = startMonitor(); - await waitForSubscribe(); - - getNotificationHandler()?.({ - method: "message", - params: { - message: { - id: 11, - chat_id: 99, - chat_name: "Test Group", - sender: "+15550001111", - is_from_me: false, - text: "@openclaw hi", - is_group: true, - created_at: "2026-01-17T00:00:00Z", - }, - }, - }); - - await flush(); - await closeMonitor(); - await run; - - expect(replyMock).toHaveBeenCalled(); - const ctx = replyMock.mock.calls[0]?.[0]; - const body = ctx?.Body ?? ""; - expect(body).toContain("Test Group id:99"); - expect(body).toContain("+15550001111: @openclaw hi"); - }); - - it("includes reply context when imessage reply metadata is present", async () => { - const run = startMonitor(); - await waitForSubscribe(); - - getNotificationHandler()?.({ - method: "message", - params: { - message: { - id: 12, - chat_id: 55, - sender: "+15550001111", - is_from_me: false, - text: "replying now", - is_group: false, - reply_to_id: 9001, - reply_to_text: "original message", - reply_to_sender: "+15559998888", - }, - }, - }); - - await flush(); - await closeMonitor(); - await run; - - expect(replyMock).toHaveBeenCalled(); - const ctx = replyMock.mock.calls[0]?.[0] as { - Body?: string; - ReplyToId?: string; - ReplyToBody?: string; - ReplyToSender?: string; - }; - expect(ctx.ReplyToId).toBe("9001"); - expect(ctx.ReplyToBody).toBe("original message"); - expect(ctx.ReplyToSender).toBe("+15559998888"); - expect(String(ctx.Body ?? "")).toContain("[Replying to +15559998888 id:9001]"); - expect(String(ctx.Body ?? "")).toContain("original message"); - }); }); diff --git a/src/imessage/monitor.test-harness.ts b/src/imessage/monitor.test-harness.ts index 8ae52ea20..156da5b85 100644 --- a/src/imessage/monitor.test-harness.ts +++ b/src/imessage/monitor.test-harness.ts @@ -112,12 +112,20 @@ vi.mock("./probe.js", () => ({ export const flush = () => new Promise((resolve) => setTimeout(resolve, 0)); export async function waitForSubscribe() { + for (let i = 0; i < 25; i += 1) { + if (state.requestMock.mock.calls.some((call) => call[0] === "watch.subscribe")) { + return; + } + // Prefer microtask turns over timers for speed. + await Promise.resolve(); + } for (let i = 0; i < 5; i += 1) { if (state.requestMock.mock.calls.some((call) => call[0] === "watch.subscribe")) { return; } await flush(); } + throw new Error("imessage test harness: watch.subscribe not observed"); } export function installMonitorIMessageProviderTestHooks() {