import { describe, expect, it } from "vitest"; import { EventBus } from "../src/http/sse.ts"; import { DEV_KEY, testApp } from "./helpers.ts"; describe("EventBus", () => { it("序号自增并按 after 补读,淘汰后标记 gap", () => { const bus = new EventBus(3); for (let i = 0; i < 5; i++) bus.publishSync("t", { i }); expect(bus.latestSeq).toBe(5); expect(bus.sinceSync(3).events.map((e) => e.seq)).toEqual([4, 5]); expect(bus.sinceSync(3).gap).toBe(false); expect(bus.sinceSync(1).gap).toBe(true); }); }); describe("GET /api/v1/events", () => { it("需要鉴权", async () => { const { app } = testApp(); expect((await app.request("/api/v1/events")).status).toBe(401); }); it("补读 after 之后的事件", async () => { const { app, bus } = testApp(); bus.publishSync("a", 1); bus.publishSync("b", 2); const ac = new AbortController(); const res = await app.request("/api/v1/events?after=1", { headers: { Authorization: `Bearer ${DEV_KEY}` }, signal: ac.signal, }); expect(res.headers.get("content-type")).toContain("text/event-stream"); const reader = res.body!.getReader(); const { value } = await reader.read(); const text = new TextDecoder().decode(value); expect(text).toContain("id: 2"); expect(text).toContain("event: b"); expect(text).not.toContain("event: a"); ac.abort(); await reader.cancel(); }); });