feat: implement comprehensive notification engine with policies, preferences, and automated dispatching services
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
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();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user