test: share telegram monitor startup helpers

This commit is contained in:
Peter Steinberger
2026-03-14 00:37:17 +00:00
parent 3850ea1e0f
commit 66aabf5eaa

View File

@@ -129,6 +129,46 @@ function mockRunOnceAndAbort(abort: AbortController) {
runSpy.mockImplementationOnce(() => makeAbortRunner(abort)); runSpy.mockImplementationOnce(() => makeAbortRunner(abort));
} }
async function expectOffsetConfirmationSkipped(offset: number | null) {
readTelegramUpdateOffsetSpy.mockResolvedValueOnce(offset);
const abort = new AbortController();
api.getUpdates.mockReset();
api.deleteWebhook.mockReset();
api.deleteWebhook.mockResolvedValueOnce(true);
mockRunOnceAndAbort(abort);
await monitorTelegramProvider({ token: "tok", abortSignal: abort.signal });
expect(api.getUpdates).not.toHaveBeenCalled();
}
async function runMonitorAndCaptureStartupOrder(params?: { persistedOffset?: number | null }) {
if (params && "persistedOffset" in params) {
readTelegramUpdateOffsetSpy.mockResolvedValueOnce(params.persistedOffset ?? null);
}
const abort = new AbortController();
const order: string[] = [];
api.getUpdates.mockReset();
api.deleteWebhook.mockReset();
api.deleteWebhook.mockImplementationOnce(async () => {
order.push("deleteWebhook");
return true;
});
if (typeof params?.persistedOffset === "number") {
api.getUpdates.mockImplementationOnce(async () => {
order.push("getUpdates");
return [];
});
}
runSpy.mockImplementationOnce(() => {
order.push("run");
return makeAbortRunner(abort);
});
await monitorTelegramProvider({ token: "tok", abortSignal: abort.signal });
return { order };
}
function mockRunOnceWithStalledPollingRunner(): { function mockRunOnceWithStalledPollingRunner(): {
stop: ReturnType<typeof vi.fn<() => void | Promise<void>>>; stop: ReturnType<typeof vi.fn<() => void | Promise<void>>>;
} { } {
@@ -349,19 +389,7 @@ describe("monitorTelegramProvider (grammY)", () => {
}); });
it("deletes webhook before starting polling", async () => { it("deletes webhook before starting polling", async () => {
const abort = new AbortController(); const { order } = await runMonitorAndCaptureStartupOrder();
const order: string[] = [];
api.deleteWebhook.mockReset();
api.deleteWebhook.mockImplementationOnce(async () => {
order.push("deleteWebhook");
return true;
});
runSpy.mockImplementationOnce(() => {
order.push("run");
return makeAbortRunner(abort);
});
await monitorTelegramProvider({ token: "tok", abortSignal: abort.signal });
expect(api.deleteWebhook).toHaveBeenCalledWith({ drop_pending_updates: false }); expect(api.deleteWebhook).toHaveBeenCalledWith({ drop_pending_updates: false });
expect(order).toEqual(["deleteWebhook", "run"]); expect(order).toEqual(["deleteWebhook", "run"]);
@@ -577,67 +605,24 @@ describe("monitorTelegramProvider (grammY)", () => {
}); });
it("confirms persisted offset with Telegram before starting runner", async () => { it("confirms persisted offset with Telegram before starting runner", async () => {
readTelegramUpdateOffsetSpy.mockResolvedValueOnce(549076203); const { order } = await runMonitorAndCaptureStartupOrder({
const abort = new AbortController(); persistedOffset: 549076203,
const order: string[] = [];
api.getUpdates.mockReset();
api.getUpdates.mockImplementationOnce(async () => {
order.push("getUpdates");
return [];
}); });
api.deleteWebhook.mockReset();
api.deleteWebhook.mockImplementationOnce(async () => {
order.push("deleteWebhook");
return true;
});
runSpy.mockImplementationOnce(() => {
order.push("run");
return makeAbortRunner(abort);
});
await monitorTelegramProvider({ token: "tok", abortSignal: abort.signal });
expect(api.getUpdates).toHaveBeenCalledWith({ offset: 549076204, limit: 1, timeout: 0 }); expect(api.getUpdates).toHaveBeenCalledWith({ offset: 549076204, limit: 1, timeout: 0 });
expect(order).toEqual(["deleteWebhook", "getUpdates", "run"]); expect(order).toEqual(["deleteWebhook", "getUpdates", "run"]);
}); });
it("skips offset confirmation when no persisted offset exists", async () => { it("skips offset confirmation when no persisted offset exists", async () => {
readTelegramUpdateOffsetSpy.mockResolvedValueOnce(null); await expectOffsetConfirmationSkipped(null);
const abort = new AbortController();
api.getUpdates.mockReset();
api.deleteWebhook.mockReset();
api.deleteWebhook.mockResolvedValueOnce(true);
mockRunOnceAndAbort(abort);
await monitorTelegramProvider({ token: "tok", abortSignal: abort.signal });
expect(api.getUpdates).not.toHaveBeenCalled();
}); });
it("skips offset confirmation when persisted offset is invalid", async () => { it("skips offset confirmation when persisted offset is invalid", async () => {
readTelegramUpdateOffsetSpy.mockResolvedValueOnce(-1 as number); await expectOffsetConfirmationSkipped(-1);
const abort = new AbortController();
api.getUpdates.mockReset();
api.deleteWebhook.mockReset();
api.deleteWebhook.mockResolvedValueOnce(true);
mockRunOnceAndAbort(abort);
await monitorTelegramProvider({ token: "tok", abortSignal: abort.signal });
expect(api.getUpdates).not.toHaveBeenCalled();
}); });
it("skips offset confirmation when persisted offset cannot be safely incremented", async () => { it("skips offset confirmation when persisted offset cannot be safely incremented", async () => {
readTelegramUpdateOffsetSpy.mockResolvedValueOnce(Number.MAX_SAFE_INTEGER); await expectOffsetConfirmationSkipped(Number.MAX_SAFE_INTEGER);
const abort = new AbortController();
api.getUpdates.mockReset();
api.deleteWebhook.mockReset();
api.deleteWebhook.mockResolvedValueOnce(true);
mockRunOnceAndAbort(abort);
await monitorTelegramProvider({ token: "tok", abortSignal: abort.signal });
expect(api.getUpdates).not.toHaveBeenCalled();
}); });
it("resets webhookCleared latch on 409 conflict so deleteWebhook re-runs", async () => { it("resets webhookCleared latch on 409 conflict so deleteWebhook re-runs", async () => {