test: align envelope timestamps with local tz

This commit is contained in:
Peter Steinberger 2026-01-22 04:49:34 +00:00
parent af42cb3ded
commit b60db040e2
4 changed files with 92 additions and 67 deletions

View File

@ -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 { resetInboundDedupe } from "../auto-reply/reply/inbound-dedupe.js";
import { createTelegramBot } from "./bot.js"; import { createTelegramBot } from "./bot.js";
@ -89,6 +89,7 @@ vi.mock("grammy", () => ({
const sequentializeMiddleware = vi.fn(); const sequentializeMiddleware = vi.fn();
const sequentializeSpy = vi.fn(() => sequentializeMiddleware); const sequentializeSpy = vi.fn(() => sequentializeMiddleware);
let _sequentializeKey: ((ctx: unknown) => string) | undefined; let _sequentializeKey: ((ctx: unknown) => string) | undefined;
let originalTz: string | undefined;
vi.mock("@grammyjs/runner", () => ({ vi.mock("@grammyjs/runner", () => ({
sequentialize: (keyFn: (ctx: unknown) => string) => { sequentialize: (keyFn: (ctx: unknown) => string) => {
_sequentializeKey = keyFn; _sequentializeKey = keyFn;
@ -120,6 +121,8 @@ const getOnHandler = (event: string) => {
describe("createTelegramBot", () => { describe("createTelegramBot", () => {
beforeEach(() => { beforeEach(() => {
originalTz = process.env.TZ;
process.env.TZ = "UTC";
resetInboundDedupe(); resetInboundDedupe();
loadConfig.mockReturnValue({ loadConfig.mockReturnValue({
channels: { channels: {
@ -138,6 +141,10 @@ describe("createTelegramBot", () => {
_sequentializeKey = undefined; _sequentializeKey = undefined;
}); });
afterEach(() => {
process.env.TZ = originalTz;
});
// groupPolicy tests // groupPolicy tests
it("accepts group messages when mentionPatterns match (without @botUsername)", async () => { it("accepts group messages when mentionPatterns match (without @botUsername)", async () => {
@ -176,7 +183,9 @@ describe("createTelegramBot", () => {
expect(payload.WasMentioned).toBe(true); expect(payload.WasMentioned).toBe(true);
expect(payload.SenderName).toBe("Ada"); expect(payload.SenderName).toBe("Ada");
expect(payload.SenderId).toBe("9"); 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 () => { it("keeps group envelope headers stable (sender identity is separate)", async () => {
onSpy.mockReset(); onSpy.mockReset();
@ -217,7 +226,7 @@ describe("createTelegramBot", () => {
expect(payload.SenderName).toBe("Ada Lovelace"); expect(payload.SenderName).toBe("Ada Lovelace");
expect(payload.SenderId).toBe("99"); expect(payload.SenderId).toBe("99");
expect(payload.SenderUsername).toBe("ada"); 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 () => { it("reacts to mention-gated group messages when ackReaction is enabled", async () => {
onSpy.mockReset(); onSpy.mockReset();

View File

@ -329,7 +329,7 @@ describe("createTelegramBot", () => {
expect(replySpy).toHaveBeenCalledTimes(1); expect(replySpy).toHaveBeenCalledTimes(1);
const payload = replySpy.mock.calls[0][0]; const payload = replySpy.mock.calls[0][0];
expect(payload.Body).toMatch( 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"); expect(payload.Body).toContain("hello world");
} finally { } finally {

View File

@ -451,7 +451,7 @@ describe("createTelegramBot", () => {
expect(replySpy).toHaveBeenCalledTimes(1); expect(replySpy).toHaveBeenCalledTimes(1);
const payload = replySpy.mock.calls[0][0]; const payload = replySpy.mock.calls[0][0];
expect(payload.Body).toMatch( 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"); expect(payload.Body).toContain("hello world");
} finally { } finally {
@ -551,10 +551,13 @@ describe("createTelegramBot", () => {
}); });
it("accepts group messages when mentionPatterns match (without @botUsername)", async () => { it("accepts group messages when mentionPatterns match (without @botUsername)", async () => {
const originalTz = process.env.TZ;
process.env.TZ = "UTC";
onSpy.mockReset(); onSpy.mockReset();
const replySpy = replyModule.__replySpy as unknown as ReturnType<typeof vi.fn>; const replySpy = replyModule.__replySpy as unknown as ReturnType<typeof vi.fn>;
replySpy.mockReset(); replySpy.mockReset();
try {
loadConfig.mockReturnValue({ loadConfig.mockReturnValue({
identity: { name: "Bert" }, identity: { name: "Bert" },
messages: { groupChat: { mentionPatterns: ["\\bbert\\b"] } }, messages: { groupChat: { mentionPatterns: ["\\bbert\\b"] } },
@ -585,16 +588,24 @@ describe("createTelegramBot", () => {
const payload = replySpy.mock.calls[0][0]; const payload = replySpy.mock.calls[0][0];
expectInboundContextContract(payload); expectInboundContextContract(payload);
expect(payload.WasMentioned).toBe(true); expect(payload.WasMentioned).toBe(true);
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 [^\]]+\]/,
);
expect(payload.SenderName).toBe("Ada"); expect(payload.SenderName).toBe("Ada");
expect(payload.SenderId).toBe("9"); expect(payload.SenderId).toBe("9");
} finally {
process.env.TZ = originalTz;
}
}); });
it("includes sender identity in group envelope headers", async () => { it("includes sender identity in group envelope headers", async () => {
const originalTz = process.env.TZ;
process.env.TZ = "UTC";
onSpy.mockReset(); onSpy.mockReset();
const replySpy = replyModule.__replySpy as unknown as ReturnType<typeof vi.fn>; const replySpy = replyModule.__replySpy as unknown as ReturnType<typeof vi.fn>;
replySpy.mockReset(); replySpy.mockReset();
try {
loadConfig.mockReturnValue({ loadConfig.mockReturnValue({
channels: { channels: {
telegram: { telegram: {
@ -627,10 +638,15 @@ describe("createTelegramBot", () => {
expect(replySpy).toHaveBeenCalledTimes(1); expect(replySpy).toHaveBeenCalledTimes(1);
const payload = replySpy.mock.calls[0][0]; const payload = replySpy.mock.calls[0][0];
expectInboundContextContract(payload); expectInboundContextContract(payload);
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 [^\]]+\]/,
);
expect(payload.SenderName).toBe("Ada Lovelace"); expect(payload.SenderName).toBe("Ada Lovelace");
expect(payload.SenderId).toBe("99"); expect(payload.SenderId).toBe("99");
expect(payload.SenderUsername).toBe("ada"); expect(payload.SenderUsername).toBe("ada");
} finally {
process.env.TZ = originalTz;
}
}); });
it("reacts to mention-gated group messages when ackReaction is enabled", async () => { it("reacts to mention-gated group messages when ackReaction is enabled", async () => {

View File

@ -329,11 +329,11 @@ describe("web auto-reply", () => {
const firstArgs = resolver.mock.calls[0][0]; const firstArgs = resolver.mock.calls[0][0];
const secondArgs = resolver.mock.calls[1][0]; const secondArgs = resolver.mock.calls[1][0];
expect(firstArgs.Body).toMatch( 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(firstArgs.Body).not.toContain("second");
expect(secondArgs.Body).toMatch( 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"); expect(secondArgs.Body).not.toContain("first");