import { test, expect } from "bun:test"; import { EventEmitter } from "node:events"; import { toRequest, writeResponse, nodeListener } from "../src/adapters/node.ts"; function mockReq(opts: { method?: string; url?: string; headers?: Record; body?: string; }): any { const em = new EventEmitter() as any; em.method = opts.method ?? "GET"; em.url = opts.url ?? "/"; em.headers = opts.headers ?? { host: "localhost" }; setTimeout(() => { if (opts.body != null) em.emit("data", Buffer.from(opts.body)); em.emit("end"); }, 0); return em; } function mockRes(): any { const chunks: Buffer[] = []; return { statusCode: 0, headers: null as any, headersSent: false, ended: false, writeHead(status: number, headers: any) { this.statusCode = status; this.headers = headers; this.headersSent = true; }, write(chunk: any) { chunks.push(Buffer.from(chunk)); }, end(chunk?: any) { if (chunk) chunks.push(Buffer.from(chunk)); this.ended = true; }, body() { return Buffer.concat(chunks).toString(); }, }; } test("toRequest converts method, URL, headers and body", async () => { const req = mockReq({ method: "POST", url: "/api/x?a=1", headers: { host: "ex.test", "content-type": "application/json" }, body: '{"k":1}', }); const r = await toRequest(req); expect(r.method).toBe("POST"); expect(r.url).toBe("http://ex.test/api/x?a=1"); expect(r.headers.get("content-type")).toBe("application/json"); expect(await r.json()).toEqual({ k: 1 }); }); test("toRequest honours x-forwarded-proto for the origin", async () => { const req = mockReq({ url: "/p", headers: { host: "ex.test", "x-forwarded-proto": "https" } }); const r = await toRequest(req); expect(r.url).toBe("https://ex.test/p"); }); test("writeResponse writes status, body and keeps multiple Set-Cookie separate", async () => { const res = mockRes(); const response = new Response("hello", { status: 201, headers: { "content-type": "text/plain" }, }); response.headers.append("set-cookie", "a=1"); response.headers.append("set-cookie", "b=2"); await writeResponse(res, response); expect(res.statusCode).toBe(201); expect(res.headers["content-type"]).toBe("text/plain"); expect(res.headers["set-cookie"]).toEqual(["a=1", "b=2"]); expect(res.body()).toBe("hello"); }); test("nodeListener dispatches a request through a fetch handler", async () => { const handler = (req: Request) => Response.json({ path: new URL(req.url).pathname }); const res = mockRes(); await nodeListener(handler)(mockReq({ url: "/hi", headers: { host: "x" } }), res); expect(res.statusCode).toBe(200); expect(JSON.parse(res.body())).toEqual({ path: "/hi" }); }); test("nodeListener returns 500 when the handler throws", async () => { const handler = () => { throw new Error("boom"); }; const res = mockRes(); await nodeListener(handler)(mockReq({ url: "/x", headers: { host: "x" } }), res); expect(res.statusCode).toBe(500); });