|
1 | 1 | /** Tests block reply pipeline buffering, dedupe, and final flush behavior. */ |
| 2 | +import { MAX_TIMER_TIMEOUT_MS } from "@openclaw/normalization-core/number-coercion"; |
2 | 3 | import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; |
3 | 4 | import { getReplyPayloadMetadata, setReplyPayloadMetadata } from "../reply-payload.js"; |
4 | 5 | import { |
@@ -449,4 +450,30 @@ describe("createBlockReplyPipeline content coverage dedup", () => {
|
449 | 450 | |
450 | 451 | expect(pipeline.hasSentPayload({ text: "summary" })).toBe(false); |
451 | 452 | }); |
| 453 | + |
| 454 | +it("clamps oversized delivery timeouts before arming timers", async () => { |
| 455 | +vi.useFakeTimers(); |
| 456 | +const setTimeoutSpy = vi.spyOn(globalThis, "setTimeout"); |
| 457 | +const observedTimeouts: number[] = []; |
| 458 | +const pipeline = createBlockReplyPipeline({ |
| 459 | +onBlockReply: async (_payload, options) => { |
| 460 | +observedTimeouts.push(options?.timeoutMs ?? 0); |
| 461 | +await waitForAbort(options?.abortSignal); |
| 462 | +}, |
| 463 | +timeoutMs: MAX_TIMER_TIMEOUT_MS + 1, |
| 464 | +}); |
| 465 | + |
| 466 | +pipeline.enqueue({ text: "slow block" }); |
| 467 | +const flushing = pipeline.flush({ force: true }); |
| 468 | +await Promise.resolve(); |
| 469 | + |
| 470 | +expect(setTimeoutSpy).toHaveBeenCalledWith(expect.any(Function), MAX_TIMER_TIMEOUT_MS); |
| 471 | +expect(observedTimeouts).toEqual([MAX_TIMER_TIMEOUT_MS]); |
| 472 | + |
| 473 | +await vi.advanceTimersByTimeAsync(MAX_TIMER_TIMEOUT_MS); |
| 474 | +await flushing; |
| 475 | + |
| 476 | +expect(pipeline.isAborted()).toBe(true); |
| 477 | +setTimeoutSpy.mockRestore(); |
| 478 | +}); |
452 | 479 | }); |