import { expect, test } from "@playwright/test"; /** * Stage-7 closure smoke — `api-sse-bun` event stream. * * Opens a real `fetch` against `/sse` to attach as an SSE subscriber, * then publishes via `/sse/publish` and asserts that the stream body * carries the expected `data:` frame. */ async function readUntilEvent( body: ReadableStream, pattern: RegExp, timeoutMs = 5000 ): Promise { const reader = body.getReader(); const decoder = new TextDecoder(); let buffer = ""; const deadline = Date.now() + timeoutMs; try { while (Date.now() < deadline) { const { value, done } = await reader.read(); if (done) break; if (value !== undefined) { buffer += decoder.decode(value, { stream: true }); if (pattern.test(buffer)) { return buffer; } } } } finally { try { await reader.cancel(); } catch { /* idempotent */ } } throw new Error( `sse stream did not yield ${pattern} within ${timeoutMs}ms; got: ${buffer}` ); } test.describe("foundation-stack-engines — sse-bun stream", () => { test("4. sse subscriber receives a published event", async ({ request, baseURL, }) => { const ac = new AbortController(); const url = `${baseURL}/sse?tenant=tenant-a&topic=ticker`; const sseResponse = await fetch(url, { method: "GET", headers: { accept: "text/event-stream", "accept-encoding": "identity", }, signal: ac.signal, }); expect(sseResponse.status).toBe(200); expect(sseResponse.headers.get("content-type")).toContain( "text/event-stream" ); expect(sseResponse.body).not.toBeNull(); // Give the handshake pipeline a moment to register the // subscription on the engine's bus. await new Promise((resolve) => setTimeout(resolve, 200)); const pub = await request.post("/sse/publish", { data: { topic: "ticker", tenant: "tenant-a", data: "hello-sse", id: "evt-1", }, }); expect(pub.status()).toBe(200); const pubBody = (await pub.json()) as { delivered: number }; expect(pubBody.delivered).toBeGreaterThanOrEqual(1); const stream = sseResponse.body as ReadableStream; const seen = await readUntilEvent(stream, /data:\s*hello-sse/); expect(seen).toContain("data: hello-sse"); expect(seen).toContain("id: evt-1"); ac.abort(); }); });