mirror of https://github.com/openclaw/openclaw.git
161 lines
3.6 KiB
TypeScript
161 lines
3.6 KiB
TypeScript
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
import {
|
|
buildTelegramErrorScopeKey,
|
|
resolveTelegramErrorPolicy,
|
|
resetTelegramErrorPolicyStoreForTest,
|
|
shouldSuppressTelegramError,
|
|
} from "./error-policy.js";
|
|
|
|
describe("telegram error policy", () => {
|
|
beforeEach(() => {
|
|
vi.useFakeTimers();
|
|
vi.setSystemTime(new Date("2026-01-01T00:00:00Z"));
|
|
resetTelegramErrorPolicyStoreForTest();
|
|
});
|
|
|
|
afterEach(() => {
|
|
resetTelegramErrorPolicyStoreForTest();
|
|
vi.useRealTimers();
|
|
});
|
|
|
|
it("resolves policy and cooldown from the most specific config", () => {
|
|
expect(
|
|
resolveTelegramErrorPolicy({
|
|
accountConfig: { errorPolicy: "once", errorCooldownMs: 1000 },
|
|
groupConfig: { errorCooldownMs: 2000 },
|
|
topicConfig: { errorPolicy: "silent" },
|
|
}),
|
|
).toEqual({
|
|
policy: "silent",
|
|
cooldownMs: 2000,
|
|
});
|
|
});
|
|
|
|
it("suppresses only repeated matching errors within the same scope", () => {
|
|
const scopeKey = buildTelegramErrorScopeKey({
|
|
accountId: "work",
|
|
chatId: 42,
|
|
threadId: 7,
|
|
});
|
|
|
|
expect(
|
|
shouldSuppressTelegramError({
|
|
scopeKey,
|
|
cooldownMs: 1000,
|
|
errorMessage: "429",
|
|
}),
|
|
).toBe(false);
|
|
expect(
|
|
shouldSuppressTelegramError({
|
|
scopeKey,
|
|
cooldownMs: 1000,
|
|
errorMessage: "429",
|
|
}),
|
|
).toBe(true);
|
|
expect(
|
|
shouldSuppressTelegramError({
|
|
scopeKey,
|
|
cooldownMs: 1000,
|
|
errorMessage: "403",
|
|
}),
|
|
).toBe(false);
|
|
});
|
|
|
|
it("keeps cooldowns per error message within the same scope", () => {
|
|
const scopeKey = buildTelegramErrorScopeKey({
|
|
accountId: "work",
|
|
chatId: 42,
|
|
});
|
|
|
|
expect(
|
|
shouldSuppressTelegramError({
|
|
scopeKey,
|
|
cooldownMs: 1000,
|
|
errorMessage: "A",
|
|
}),
|
|
).toBe(false);
|
|
expect(
|
|
shouldSuppressTelegramError({
|
|
scopeKey,
|
|
cooldownMs: 1000,
|
|
errorMessage: "B",
|
|
}),
|
|
).toBe(false);
|
|
expect(
|
|
shouldSuppressTelegramError({
|
|
scopeKey,
|
|
cooldownMs: 1000,
|
|
errorMessage: "A",
|
|
}),
|
|
).toBe(true);
|
|
});
|
|
|
|
it("prunes expired cooldowns within a single scope", () => {
|
|
const scopeKey = buildTelegramErrorScopeKey({
|
|
accountId: "work",
|
|
chatId: 42,
|
|
});
|
|
|
|
expect(
|
|
shouldSuppressTelegramError({
|
|
scopeKey,
|
|
cooldownMs: 1000,
|
|
errorMessage: "A",
|
|
}),
|
|
).toBe(false);
|
|
vi.advanceTimersByTime(1001);
|
|
expect(
|
|
shouldSuppressTelegramError({
|
|
scopeKey,
|
|
cooldownMs: 1000,
|
|
errorMessage: "B",
|
|
}),
|
|
).toBe(false);
|
|
expect(
|
|
shouldSuppressTelegramError({
|
|
scopeKey,
|
|
cooldownMs: 1000,
|
|
errorMessage: "A",
|
|
}),
|
|
).toBe(false);
|
|
});
|
|
|
|
it("does not leak suppression across accounts or threads", () => {
|
|
const workMain = buildTelegramErrorScopeKey({
|
|
accountId: "work",
|
|
chatId: 42,
|
|
});
|
|
const personalMain = buildTelegramErrorScopeKey({
|
|
accountId: "personal",
|
|
chatId: 42,
|
|
});
|
|
const workTopic = buildTelegramErrorScopeKey({
|
|
accountId: "work",
|
|
chatId: 42,
|
|
threadId: 9,
|
|
});
|
|
|
|
expect(
|
|
shouldSuppressTelegramError({
|
|
scopeKey: workMain,
|
|
cooldownMs: 1000,
|
|
errorMessage: "429",
|
|
}),
|
|
).toBe(false);
|
|
expect(
|
|
shouldSuppressTelegramError({
|
|
scopeKey: personalMain,
|
|
cooldownMs: 1000,
|
|
errorMessage: "429",
|
|
}),
|
|
).toBe(false);
|
|
expect(
|
|
shouldSuppressTelegramError({
|
|
scopeKey: workTopic,
|
|
cooldownMs: 1000,
|
|
errorMessage: "429",
|
|
}),
|
|
).toBe(false);
|
|
});
|
|
});
|