test(telegram): cover polling after webhook cleanup timeout

This commit is contained in:
Ayaan Zaidi
2026-05-03 20:07:24 +05:30
committed by Peter Steinberger
parent f8141da4a6
commit 81ece77f8c
2 changed files with 35 additions and 26 deletions

View File

@@ -495,50 +495,35 @@ describe("monitorTelegramProvider (grammY)", () => {
expect(order).toEqual(["deleteWebhook", "run"]);
});
it("retries recoverable deleteWebhook failures before polling", async () => {
it("starts polling after recoverable deleteWebhook failures", async () => {
const abort = new AbortController();
const cleanupError = makeRecoverableFetchError();
api.deleteWebhook.mockReset();
api.getWebhookInfo.mockReset().mockResolvedValueOnce({ url: "https://example.test/hook" });
api.deleteWebhook.mockRejectedValueOnce(cleanupError).mockResolvedValueOnce(true);
mockRunOnceAndAbort(abort);
await monitorTelegramProvider({ token: "tok", abortSignal: abort.signal });
expect(api.deleteWebhook).toHaveBeenCalledTimes(2);
expect(api.getWebhookInfo).toHaveBeenCalledTimes(1);
expectRecoverableRetryState(1);
});
it("continues polling when deleteWebhook transiently fails but webhook is already absent", async () => {
const abort = new AbortController();
const cleanupError = makeRecoverableFetchError();
api.deleteWebhook.mockReset();
api.getWebhookInfo.mockReset().mockResolvedValueOnce({ url: "" });
api.getWebhookInfo.mockReset();
api.deleteWebhook.mockRejectedValueOnce(cleanupError);
mockRunOnceAndAbort(abort);
await monitorTelegramProvider({ token: "tok", abortSignal: abort.signal });
expect(api.deleteWebhook).toHaveBeenCalledTimes(1);
expect(api.getWebhookInfo).toHaveBeenCalledTimes(1);
expect(runSpy).toHaveBeenCalledTimes(1);
expect(sleepWithAbort).not.toHaveBeenCalled();
expect(api.getWebhookInfo).not.toHaveBeenCalled();
expectRecoverableRetryState(1);
});
it("retries cleanup when deleteWebhook and webhook confirmation both transiently fail", async () => {
it("does not run webhook confirmation when deleteWebhook transiently fails", async () => {
const abort = new AbortController();
const cleanupError = makeRecoverableFetchError();
api.deleteWebhook.mockReset();
api.getWebhookInfo.mockReset().mockRejectedValueOnce(makeRecoverableFetchError());
api.deleteWebhook.mockRejectedValueOnce(cleanupError).mockResolvedValueOnce(true);
api.getWebhookInfo.mockReset();
api.deleteWebhook.mockRejectedValueOnce(cleanupError);
mockRunOnceAndAbort(abort);
await monitorTelegramProvider({ token: "tok", abortSignal: abort.signal });
expect(api.deleteWebhook).toHaveBeenCalledTimes(2);
expect(api.getWebhookInfo).toHaveBeenCalledTimes(1);
expectRecoverableRetryState(1);
expect(api.deleteWebhook).toHaveBeenCalledTimes(1);
expect(api.getWebhookInfo).not.toHaveBeenCalled();
expect(runSpy).toHaveBeenCalledTimes(1);
expect(sleepWithAbort).not.toHaveBeenCalled();
});
it("retries setup-time recoverable errors before starting polling", async () => {

View File

@@ -572,6 +572,30 @@ describe("TelegramPollingSession", () => {
expect(createTelegramTransport).toHaveBeenCalledTimes(1);
});
it("starts polling when webhook cleanup times out during startup", async () => {
const abort = new AbortController();
const cleanupError = new Error("Telegram deleteWebhook timed out after 15000ms");
const bot = makeBot();
bot.api.deleteWebhook.mockRejectedValueOnce(cleanupError);
createTelegramBotMock.mockReturnValueOnce(bot);
runMock.mockReturnValueOnce({
task: async () => {
abort.abort();
},
stop: vi.fn(async () => undefined),
isRunning: () => false,
});
const session = createPollingSession({
abortSignal: abort.signal,
});
await session.runUntilAbort();
expect(bot.api.deleteWebhook).toHaveBeenCalledTimes(1);
expect(runMock).toHaveBeenCalledTimes(1);
});
it("does not trigger stall restart shortly after a getUpdates error", async () => {
const abort = new AbortController();
const botStop = vi.fn(async () => undefined);