mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-08 05:00:43 +00:00
test(telegram): lock draft finalization ordering
This commit is contained in:
@@ -924,6 +924,24 @@ describe("dispatchTelegramMessage draft streaming", () => {
|
||||
expect(deliverReplies).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("waits for queued draft-lane partials before finalizing the Telegram reply", async () => {
|
||||
const { answerDraftStream } = setupDraftStreams({ answerMessageId: 2001 });
|
||||
dispatchReplyWithBufferedBlockDispatcher.mockImplementation(
|
||||
async ({ dispatcherOptions, replyOptions }) => {
|
||||
const pendingPartial = replyOptions?.onPartialReply?.({ text: "Working" });
|
||||
await dispatcherOptions.deliver({ text: "Done" }, { kind: "final" });
|
||||
await pendingPartial;
|
||||
return { queuedFinal: true };
|
||||
},
|
||||
);
|
||||
|
||||
await dispatchWithContext({ context: createContext() });
|
||||
|
||||
expect(answerDraftStream.update).toHaveBeenNthCalledWith(1, "Working");
|
||||
expect(answerDraftStream.update).toHaveBeenNthCalledWith(2, "Done");
|
||||
expect(deliverReplies).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("keeps progress updates in a draft and sends the final answer normally", async () => {
|
||||
const { answerDraftStream } = setupDraftStreams({ answerMessageId: 2001 });
|
||||
dispatchReplyWithBufferedBlockDispatcher.mockImplementation(
|
||||
|
||||
@@ -120,6 +120,68 @@ describe("draft-stream-controls", () => {
|
||||
expect(deleteMessage).toHaveBeenCalledWith("m-4");
|
||||
});
|
||||
|
||||
it("lifecycle clear cancels pending draft text instead of flushing it", async () => {
|
||||
vi.useFakeTimers();
|
||||
vi.setSystemTime(0);
|
||||
try {
|
||||
const state = { stopped: false, final: false };
|
||||
let messageId: string | undefined = "m-6";
|
||||
const sendOrEditStreamMessage = vi.fn(async () => true);
|
||||
const deleteMessage = vi.fn(async () => {});
|
||||
|
||||
const lifecycle = createFinalizableDraftLifecycle({
|
||||
throttleMs: 250,
|
||||
state,
|
||||
sendOrEditStreamMessage,
|
||||
readMessageId: () => messageId,
|
||||
clearMessageId: () => {
|
||||
messageId = undefined;
|
||||
},
|
||||
isValidMessageId: (value): value is string => typeof value === "string",
|
||||
deleteMessage,
|
||||
warnPrefix: "cleanup failed",
|
||||
});
|
||||
|
||||
lifecycle.update("pending draft");
|
||||
await lifecycle.clear();
|
||||
|
||||
expect(state.stopped).toBe(true);
|
||||
expect(sendOrEditStreamMessage).not.toHaveBeenCalled();
|
||||
expect(deleteMessage).toHaveBeenCalledWith("m-6");
|
||||
} finally {
|
||||
vi.useRealTimers();
|
||||
}
|
||||
});
|
||||
|
||||
it("lifecycle stop flushes pending final draft text", async () => {
|
||||
vi.useFakeTimers();
|
||||
vi.setSystemTime(0);
|
||||
try {
|
||||
const state = { stopped: false, final: false };
|
||||
const sendOrEditStreamMessage = vi.fn(async () => true);
|
||||
|
||||
const lifecycle = createFinalizableDraftLifecycle({
|
||||
throttleMs: 250,
|
||||
state,
|
||||
sendOrEditStreamMessage,
|
||||
readMessageId: () => "m-7",
|
||||
clearMessageId: () => {},
|
||||
isValidMessageId: (value): value is string => typeof value === "string",
|
||||
deleteMessage: async () => {},
|
||||
warnPrefix: "cleanup failed",
|
||||
});
|
||||
|
||||
lifecycle.update("final draft");
|
||||
await lifecycle.stop();
|
||||
|
||||
expect(state.final).toBe(true);
|
||||
expect(sendOrEditStreamMessage).toHaveBeenCalledTimes(1);
|
||||
expect(sendOrEditStreamMessage).toHaveBeenCalledWith("final draft");
|
||||
} finally {
|
||||
vi.useRealTimers();
|
||||
}
|
||||
});
|
||||
|
||||
it("lifecycle seal ignores late updates without clearing the preview id", async () => {
|
||||
const state = { stopped: false, final: false };
|
||||
let messageId: string | undefined = "m-5";
|
||||
|
||||
Reference in New Issue
Block a user