diff --git a/test/js/node/http/node-http.test.ts b/test/js/node/http/node-http.test.ts index e5f6a9431d..6e18d98695 100644 --- a/test/js/node/http/node-http.test.ts +++ b/test/js/node/http/node-http.test.ts @@ -133,6 +133,51 @@ describe("node:http", () => { } }); + it("response body streaming is immediate (#13696)", async () => { + const totalChunks = 10; + const spacing = 50; + const acceptableDelay = 20; + + try { + var server = createServer(async (req, res) => { + res.writeHead(200, { "Content-Type": "text/plain" }); + for (let i = 0; i < totalChunks; i++) { + res.write(new Date().getTime().toString() + "\n"); + + if (i + 1 < totalChunks) await Bun.sleep(spacing); + } + res.end(); + }); + const url = await listen(server); + const res = await fetch(url); + const reader = res.body.getReader(); + const decoder = new TextDecoder(); + + let receivedChunks = 0; + while (true) { + const { done, value } = await reader.read(); + if (done) break; + + receivedChunks++; + + // Verify that chunks are not held up longer than necessary + // at the receiver. This is likely to be in the single digits. + // + // #13696: Bun would delay the initial chunks and then send multiple + // chunks before real-time streaming started working. + expect( + new Date().getTime() - parseInt(decoder.decode(value).trimEnd()) + ).toBeLessThan(acceptableDelay); + } + + // Verify that the correct number of chunks were sent (in case server + // decides to send no chunks at all). + expect(receivedChunks).toEqual(totalChunks); + } finally { + server.close(); + } + }); + it("listen should return server", async () => { const server = createServer(); const listenResponse = server.listen(0);