import { createServer, type ServerResponse } from "node:http"; import type { AddressInfo } from "node:net"; import type { Page } from "@playwright/test"; const fixtures = new WeakMap(); // route.fulfill() closes an SSE response after its body. UI fixtures need a // real open response so the application stays live until the page disconnects. export async function mockWorkbenchEventStream(page: Page) { const existing = fixtures.get(page); if (existing) return existing; const clients = new Set(); const cursors: string[] = []; const server = createServer((request, response) => { response.setHeader("Access-Control-Allow-Origin", "*"); response.setHeader("Access-Control-Allow-Headers", "Authorization, Content-Type, Last-Event-ID, X-Project-Id"); response.setHeader("Access-Control-Allow-Methods", "GET, OPTIONS"); if (request.method === "OPTIONS") { response.writeHead(204).end(); return; } cursors.push(new URL(request.url!, "http://localhost").searchParams.get("after") ?? ""); response.writeHead(200, { "Content-Type": "text/event-stream", "Cache-Control": "no-cache" }); response.write(": fixture connected\n\n"); clients.add(response); response.on("close", () => clients.delete(response)); }); await new Promise((resolve, reject) => { server.once("error", reject); server.listen(0, "127.0.0.1", resolve); }); const { port } = server.address() as AddressInfo; page.on("close", () => { for (const client of clients) client.destroy(); server.close(); server.closeAllConnections(); }); await page.route("**/api/v1/workbench/events**", (route) => { const query = new URL(route.request().url()).search; return route.fulfill({ status: 307, headers: { "Access-Control-Allow-Origin": "*", "Location": `http://127.0.0.1:${port}/events${query}` } }); }); const fixture = { cursors }; fixtures.set(page, fixture); return fixture; }