From b60db040e26d3ea6bdb0bc0e13757edaff9b710c Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Thu, 22 Jan 2026 04:49:34 +0000 Subject: [PATCH] test: align envelope timestamps with local tz --- ...patterns-match-without-botusername.test.ts | 15 +- ...gram-bot.installs-grammy-throttler.test.ts | 2 +- src/telegram/bot.test.ts | 138 ++++++++++-------- ....reconnects-after-connection-close.test.ts | 4 +- 4 files changed, 92 insertions(+), 67 deletions(-) diff --git a/src/telegram/bot.create-telegram-bot.accepts-group-messages-mentionpatterns-match-without-botusername.test.ts b/src/telegram/bot.create-telegram-bot.accepts-group-messages-mentionpatterns-match-without-botusername.test.ts index 7134d7d3b..eae2de919 100644 --- a/src/telegram/bot.create-telegram-bot.accepts-group-messages-mentionpatterns-match-without-botusername.test.ts +++ b/src/telegram/bot.create-telegram-bot.accepts-group-messages-mentionpatterns-match-without-botusername.test.ts @@ -1,4 +1,4 @@ -import { beforeEach, describe, expect, it, vi } from "vitest"; +import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import { resetInboundDedupe } from "../auto-reply/reply/inbound-dedupe.js"; import { createTelegramBot } from "./bot.js"; @@ -89,6 +89,7 @@ vi.mock("grammy", () => ({ const sequentializeMiddleware = vi.fn(); const sequentializeSpy = vi.fn(() => sequentializeMiddleware); let _sequentializeKey: ((ctx: unknown) => string) | undefined; +let originalTz: string | undefined; vi.mock("@grammyjs/runner", () => ({ sequentialize: (keyFn: (ctx: unknown) => string) => { _sequentializeKey = keyFn; @@ -120,6 +121,8 @@ const getOnHandler = (event: string) => { describe("createTelegramBot", () => { beforeEach(() => { + originalTz = process.env.TZ; + process.env.TZ = "UTC"; resetInboundDedupe(); loadConfig.mockReturnValue({ channels: { @@ -138,6 +141,10 @@ describe("createTelegramBot", () => { _sequentializeKey = undefined; }); + afterEach(() => { + process.env.TZ = originalTz; + }); + // groupPolicy tests it("accepts group messages when mentionPatterns match (without @botUsername)", async () => { @@ -176,7 +183,9 @@ describe("createTelegramBot", () => { expect(payload.WasMentioned).toBe(true); expect(payload.SenderName).toBe("Ada"); expect(payload.SenderId).toBe("9"); - expect(payload.Body).toMatch(/^\[Telegram Test Group id:7 (\+\d+[smhd] )?2025-01-09T00:00Z\]/); + expect(payload.Body).toMatch( + /^\[Telegram Test Group id:7 (\+\d+[smhd] )?2025-01-09 00:00 [^\]]+\]/, + ); }); it("keeps group envelope headers stable (sender identity is separate)", async () => { onSpy.mockReset(); @@ -217,7 +226,7 @@ describe("createTelegramBot", () => { expect(payload.SenderName).toBe("Ada Lovelace"); expect(payload.SenderId).toBe("99"); expect(payload.SenderUsername).toBe("ada"); - expect(payload.Body).toMatch(/^\[Telegram Ops id:42 (\+\d+[smhd] )?2025-01-09T00:00Z\]/); + expect(payload.Body).toMatch(/^\[Telegram Ops id:42 (\+\d+[smhd] )?2025-01-09 00:00 [^\]]+\]/); }); it("reacts to mention-gated group messages when ackReaction is enabled", async () => { onSpy.mockReset(); diff --git a/src/telegram/bot.create-telegram-bot.installs-grammy-throttler.test.ts b/src/telegram/bot.create-telegram-bot.installs-grammy-throttler.test.ts index de7f6b62b..cabdfeae7 100644 --- a/src/telegram/bot.create-telegram-bot.installs-grammy-throttler.test.ts +++ b/src/telegram/bot.create-telegram-bot.installs-grammy-throttler.test.ts @@ -329,7 +329,7 @@ describe("createTelegramBot", () => { expect(replySpy).toHaveBeenCalledTimes(1); const payload = replySpy.mock.calls[0][0]; expect(payload.Body).toMatch( - /^\[Telegram Ada Lovelace \(@ada_bot\) id:1234 (\+\d+[smhd] )?2025-01-09T00:00Z\]/, + /^\[Telegram Ada Lovelace \(@ada_bot\) id:1234 (\+\d+[smhd] )?2025-01-09 01:00 [^\]]+\]/, ); expect(payload.Body).toContain("hello world"); } finally { diff --git a/src/telegram/bot.test.ts b/src/telegram/bot.test.ts index 77f50b41f..2e7c86cf8 100644 --- a/src/telegram/bot.test.ts +++ b/src/telegram/bot.test.ts @@ -451,7 +451,7 @@ describe("createTelegramBot", () => { expect(replySpy).toHaveBeenCalledTimes(1); const payload = replySpy.mock.calls[0][0]; expect(payload.Body).toMatch( - /^\[Telegram Ada Lovelace \(@ada_bot\) id:1234 (\+\d+[smhd] )?2025-01-09T00:00Z\]/, + /^\[Telegram Ada Lovelace \(@ada_bot\) id:1234 (\+\d+[smhd] )?2025-01-09 01:00 [^\]]+\]/, ); expect(payload.Body).toContain("hello world"); } finally { @@ -551,86 +551,102 @@ describe("createTelegramBot", () => { }); it("accepts group messages when mentionPatterns match (without @botUsername)", async () => { + const originalTz = process.env.TZ; + process.env.TZ = "UTC"; onSpy.mockReset(); const replySpy = replyModule.__replySpy as unknown as ReturnType; replySpy.mockReset(); - loadConfig.mockReturnValue({ - identity: { name: "Bert" }, - messages: { groupChat: { mentionPatterns: ["\\bbert\\b"] } }, - channels: { - telegram: { - groupPolicy: "open", - groups: { "*": { requireMention: true } }, + try { + loadConfig.mockReturnValue({ + identity: { name: "Bert" }, + messages: { groupChat: { mentionPatterns: ["\\bbert\\b"] } }, + channels: { + telegram: { + groupPolicy: "open", + groups: { "*": { requireMention: true } }, + }, }, - }, - }); + }); - createTelegramBot({ token: "tok" }); - const handler = getOnHandler("message") as (ctx: Record) => Promise; + createTelegramBot({ token: "tok" }); + const handler = getOnHandler("message") as (ctx: Record) => Promise; - await handler({ - message: { - chat: { id: 7, type: "group", title: "Test Group" }, - text: "bert: introduce yourself", - date: 1736380800, - message_id: 1, - from: { id: 9, first_name: "Ada" }, - }, - me: { username: "clawdbot_bot" }, - getFile: async () => ({ download: async () => new Uint8Array() }), - }); + await handler({ + message: { + chat: { id: 7, type: "group", title: "Test Group" }, + text: "bert: introduce yourself", + date: 1736380800, + message_id: 1, + from: { id: 9, first_name: "Ada" }, + }, + me: { username: "clawdbot_bot" }, + getFile: async () => ({ download: async () => new Uint8Array() }), + }); - expect(replySpy).toHaveBeenCalledTimes(1); - const payload = replySpy.mock.calls[0][0]; - expectInboundContextContract(payload); - expect(payload.WasMentioned).toBe(true); - expect(payload.Body).toMatch(/^\[Telegram Test Group id:7 (\+\d+[smhd] )?2025-01-09T00:00Z\]/); - expect(payload.SenderName).toBe("Ada"); - expect(payload.SenderId).toBe("9"); + expect(replySpy).toHaveBeenCalledTimes(1); + const payload = replySpy.mock.calls[0][0]; + expectInboundContextContract(payload); + expect(payload.WasMentioned).toBe(true); + expect(payload.Body).toMatch( + /^\[Telegram Test Group id:7 (\+\d+[smhd] )?2025-01-09 00:00 [^\]]+\]/, + ); + expect(payload.SenderName).toBe("Ada"); + expect(payload.SenderId).toBe("9"); + } finally { + process.env.TZ = originalTz; + } }); it("includes sender identity in group envelope headers", async () => { + const originalTz = process.env.TZ; + process.env.TZ = "UTC"; onSpy.mockReset(); const replySpy = replyModule.__replySpy as unknown as ReturnType; replySpy.mockReset(); - loadConfig.mockReturnValue({ - channels: { - telegram: { - groupPolicy: "open", - groups: { "*": { requireMention: false } }, + try { + loadConfig.mockReturnValue({ + channels: { + telegram: { + groupPolicy: "open", + groups: { "*": { requireMention: false } }, + }, }, - }, - }); + }); - createTelegramBot({ token: "tok" }); - const handler = getOnHandler("message") as (ctx: Record) => Promise; + createTelegramBot({ token: "tok" }); + const handler = getOnHandler("message") as (ctx: Record) => Promise; - await handler({ - message: { - chat: { id: 42, type: "group", title: "Ops" }, - text: "hello", - date: 1736380800, - message_id: 2, - from: { - id: 99, - first_name: "Ada", - last_name: "Lovelace", - username: "ada", + await handler({ + message: { + chat: { id: 42, type: "group", title: "Ops" }, + text: "hello", + date: 1736380800, + message_id: 2, + from: { + id: 99, + first_name: "Ada", + last_name: "Lovelace", + username: "ada", + }, }, - }, - me: { username: "clawdbot_bot" }, - getFile: async () => ({ download: async () => new Uint8Array() }), - }); + me: { username: "clawdbot_bot" }, + getFile: async () => ({ download: async () => new Uint8Array() }), + }); - expect(replySpy).toHaveBeenCalledTimes(1); - const payload = replySpy.mock.calls[0][0]; - expectInboundContextContract(payload); - expect(payload.Body).toMatch(/^\[Telegram Ops id:42 (\+\d+[smhd] )?2025-01-09T00:00Z\]/); - expect(payload.SenderName).toBe("Ada Lovelace"); - expect(payload.SenderId).toBe("99"); - expect(payload.SenderUsername).toBe("ada"); + expect(replySpy).toHaveBeenCalledTimes(1); + const payload = replySpy.mock.calls[0][0]; + expectInboundContextContract(payload); + expect(payload.Body).toMatch( + /^\[Telegram Ops id:42 (\+\d+[smhd] )?2025-01-09 00:00 [^\]]+\]/, + ); + expect(payload.SenderName).toBe("Ada Lovelace"); + expect(payload.SenderId).toBe("99"); + expect(payload.SenderUsername).toBe("ada"); + } finally { + process.env.TZ = originalTz; + } }); it("reacts to mention-gated group messages when ackReaction is enabled", async () => { diff --git a/src/web/auto-reply.web-auto-reply.reconnects-after-connection-close.test.ts b/src/web/auto-reply.web-auto-reply.reconnects-after-connection-close.test.ts index 411875e21..b9a15e869 100644 --- a/src/web/auto-reply.web-auto-reply.reconnects-after-connection-close.test.ts +++ b/src/web/auto-reply.web-auto-reply.reconnects-after-connection-close.test.ts @@ -329,11 +329,11 @@ describe("web auto-reply", () => { const firstArgs = resolver.mock.calls[0][0]; const secondArgs = resolver.mock.calls[1][0]; expect(firstArgs.Body).toMatch( - /\[WhatsApp \+1 (\+\d+[smhd] )?2025-01-01T00:00Z\] \[clawdbot\] first/, + /\[WhatsApp \+1 (\+\d+[smhd] )?2025-01-01 01:00 [^\]]+\] \[clawdbot\] first/, ); expect(firstArgs.Body).not.toContain("second"); expect(secondArgs.Body).toMatch( - /\[WhatsApp \+1 (\+\d+[smhd] )?2025-01-01T01:00Z\] \[clawdbot\] second/, + /\[WhatsApp \+1 (\+\d+[smhd] )?2025-01-01 02:00 [^\]]+\] \[clawdbot\] second/, ); expect(secondArgs.Body).not.toContain("first");