describe("WhatsAppThrottle", () => { let WhatsAppThrottle: typeof import("../WhatsAppThrottle.js").WhatsAppThrottleClass; beforeAll(async () => { const mod = await import("../WhatsAppThrottle.js"); WhatsAppThrottle = mod.WhatsAppThrottleClass; }); beforeEach(() => { jest.restoreAllMocks(); }); it("allows first send for a company immediately", () => { const throttle = new WhatsAppThrottle(8000); expect(throttle.canSend("company-1")).toBe(true); }); it("blocks send within minimum interval", () => { const throttle = new WhatsAppThrottle(8000); throttle.recordSent("company-1"); jest.useFakeTimers(); jest.setSystemTime(new Date("2026-07-21T12:00:03.000Z")); // 3s later expect(throttle.canSend("company-1")).toBe(false); jest.useRealTimers(); }); it("allows send after maximum possible interval (base + jitter)", () => { const throttle = new WhatsAppThrottle(8000); const now = new Date("2026-07-21T12:00:00.000Z"); jest.useFakeTimers(); jest.setSystemTime(now); throttle.recordSent("company-1"); // After 16s (max = 8s base + 8s jitter), should always be allowed jest.setSystemTime(new Date("2026-07-21T12:00:16.000Z")); expect(throttle.canSend("company-1")).toBe(true); jest.useRealTimers(); }); it("tracks companies independently", () => { const throttle = new WhatsAppThrottle(8000); const now = new Date("2026-07-21T12:00:00.000Z"); jest.useFakeTimers(); jest.setSystemTime(now); throttle.recordSent("company-1"); // company-2 should still be allowed expect(throttle.canSend("company-2")).toBe(true); jest.useRealTimers(); }); it("applies jitter to minimum interval", () => { const throttle = new WhatsAppThrottle(8000); const now = new Date("2026-07-21T12:00:00.000Z"); jest.useFakeTimers(); jest.setSystemTime(now); throttle.recordSent("company-1"); // At exactly 8s (base interval), it should still be blocked due to jitter jest.setSystemTime(new Date("2026-07-21T12:00:08.000Z")); expect(throttle.canSend("company-1")).toBe(false); // At 16s (max interval = base + jitter), it should be allowed jest.setSystemTime(new Date("2026-07-21T12:00:16.000Z")); expect(throttle.canSend("company-1")).toBe(true); jest.useRealTimers(); }); it("uses default interval of 8000ms when not specified", () => { const throttle = new WhatsAppThrottle(); const now = new Date("2026-07-21T12:00:00.000Z"); jest.useFakeTimers(); jest.setSystemTime(now); throttle.recordSent("company-1"); // 7s should be blocked jest.setSystemTime(new Date("2026-07-21T12:00:07.000Z")); expect(throttle.canSend("company-1")).toBe(false); jest.useRealTimers(); }); });