stream.update("Hello, this is a complete response for finalization testing.");
await flushStreamTimer();
await stream.finalize();
// Find the final message activity const finalActivity = sent.find((a) => (a as Record<string, unknown>).type === "message") as
| Record<string, unknown>
| undefined;
expect(finalActivity).toBeDefined();
expect(finalActivity!.text).toBe( "Hello, this is a complete response for finalization testing.",
); // No cursor in final
expect(finalActivity!.text as string).not.toContain("\u258D");
// Should have AI-generated entity const entities = finalActivity!.entities as Array<Record<string, unknown>>;
expect(entities).toEqual(
expect.arrayContaining([expect.objectContaining({ additionalType: ["AIGeneratedContent"] })]),
);
// Should have streaminfo with final type
expect(entities).toEqual(
expect.arrayContaining([
expect.objectContaining({ type: "streaminfo", streamType: "final" }),
]),
);
});
it("does not send below MIN_INITIAL_CHARS", async () => {
vi.useFakeTimers();
const sendActivity = vi.fn(async () => ({ id: "x" })); const stream = new TeamsHttpStream({ sendActivity, throttleMs: 1 });
stream.update("Hi");
await flushStreamTimer();
expect(sendActivity).not.toHaveBeenCalled();
});
it("finalize with no content does nothing", async () => { const sendActivity = vi.fn(async () => ({ id: "x" })); const stream = new TeamsHttpStream({ sendActivity });
it("finalize sends content even if no chunks were streamed", async () => { const sent: unknown[] = []; const stream = new TeamsHttpStream({
sendActivity: vi.fn(async (activity) => {
sent.push(activity); return { id: "msg-1" };
}),
});
// Short text — below MIN_INITIAL_CHARS, so no streaming chunk sent
stream.update("Short");
await stream.finalize();
// Should send final message even though no chunks were streamed
expect(sent.length).toBe(1); const activity = sent[0] as Record<string, unknown>;
expect(activity.type).toBe("message");
expect(activity.text).toBe("Short");
});
it("sets feedbackLoopEnabled on final message", async () => {
vi.useFakeTimers();
await stream.sendInformativeUpdate("Working...");
stream.update("Hello, this is a long enough response for streaming to begin.");
await flushStreamTimer();
// Second activity (streaming chunk) should have the streamId from the informative update
expect(sent.length).toBeGreaterThanOrEqual(2); const chunk = sent[1] as Record<string, unknown>; const entities = chunk.entities as Array<Record<string, unknown>>;
expect(entities).toEqual(
expect.arrayContaining([
expect.objectContaining({ type: "streaminfo", streamId: "stream-1" }),
]),
);
});
it("hasContent is true after update", () => { const stream = new TeamsHttpStream({
sendActivity: vi.fn(async () => ({ id: "x" })),
});
it("double finalize is a no-op", async () => { const sendActivity = vi.fn(async () => ({ id: "x" })); const stream = new TeamsHttpStream({ sendActivity });
stream.update("A response long enough to pass the minimum character threshold.");
await stream.finalize(); const callCount = sendActivity.mock.calls.length;
stream.update("Hello, this is a long enough response for streaming to begin.");
await vi.advanceTimersByTimeAsync(1);
stream.update( "Hello, this is a long enough response for streaming to begin. More text before timeout.",
);
await vi.advanceTimersByTimeAsync(1);
vi.setSystemTime(new Date(Date.now() + 45_001));
stream.update( "Hello, this is a long enough response for streaming to begin. More text before timeout. Even more text after timeout.",
);
await vi.advanceTimersByTimeAsync(1);
expect(stream.isFailed).toBe(true);
const finalActivity = sent.find((a) => (a as Record<string, unknown>).type === "message") as
| Record<string, unknown>
| undefined;
expect(finalActivity).toBeDefined();
expect(finalActivity!.text).toBe( "Hello, this is a long enough response for streaming to begin. More text before timeout.",
);
});
});
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.15 Sekunden
(vorverarbeitet am 2026-05-26)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.