import { describe, expect, it } from "vite-plus/test"; import { decideThreadResume, threadReplayEncodedBytes, THREAD_RESUME_MAX_REPLAY_ENCODED_BYTES, THREAD_RESUME_MAX_REPLAY_EVENTS, } from "./ThreadStream.ts"; describe("decideThreadResume", () => { it("replays when the gap is zero", () => { expect( decideThreadResume({ afterSequence: 10, highWater: 10, replayEventCount: 0, replayEncodedBytes: 0, }), ).toEqual({ mode: "replay", afterSequence: 10, throughSequence: 10 }); }); it("replays when the event count is within the bound", () => { expect( decideThreadResume({ afterSequence: 10, highWater: 20_000, replayEventCount: THREAD_RESUME_MAX_REPLAY_EVENTS, replayEncodedBytes: THREAD_RESUME_MAX_REPLAY_ENCODED_BYTES, }), ).toEqual({ mode: "replay", afterSequence: 10, throughSequence: 20_000, }); }); it("falls back to a snapshot when the event count exceeds the bound", () => { expect( decideThreadResume({ afterSequence: 10, highWater: 20_000, replayEventCount: THREAD_RESUME_MAX_REPLAY_EVENTS + 1, replayEncodedBytes: 1, }), ).toEqual({ mode: "snapshot" }); }); it("falls back to a snapshot when encoded replay bytes exceed the bound", () => { expect( decideThreadResume({ afterSequence: 10, highWater: 11, replayEventCount: 1, replayEncodedBytes: THREAD_RESUME_MAX_REPLAY_ENCODED_BYTES + 1, }), ).toEqual({ mode: "snapshot" }); }); it("falls back to a snapshot when the client cursor is ahead of the store", () => { expect( decideThreadResume({ afterSequence: 50, highWater: 40, replayEventCount: 0, replayEncodedBytes: 0, }), ).toEqual({ mode: "snapshot" }); }); it("counts UTF-8 bytes across projected stream items", () => { expect(threadReplayEncodedBytes([{ value: "a" }, { value: "🦊" }])).toBe( Buffer.byteLength('{"value":"a"}', "utf8") + Buffer.byteLength('{"value":"🦊"}', "utf8"), ); }); });