import { expect, test } from "bun:test"; test("Request with streaming body can be cloned", async () => { const stream = new ReadableStream({ start(controller) { controller.enqueue("Hello"); controller.enqueue(" "); controller.enqueue("World"); controller.close(); }, }); const request = new Request("https://example.com", { method: "POST", body: stream }); const clonedRequest = request.clone(); const originalBody = await request.text(); const clonedBody = await clonedRequest.text(); expect(originalBody).toBe("Hello World"); expect(clonedBody).toBe("Hello World"); }); test("Response with streaming body can be cloned", async () => { const stream = new ReadableStream({ start(controller) { controller.enqueue("Test"); controller.enqueue(" "); controller.enqueue("Data"); controller.close(); }, }); const response = new Response(stream); const clonedResponse = response.clone(); const originalBody = await response.text(); const clonedBody = await clonedResponse.text(); expect(originalBody).toBe("Test Data"); expect(clonedBody).toBe("Test Data"); }); test("Request with large streaming body can be cloned", async () => { let largeData = "x".repeat(1024 * 1024); // 1MB of data let chunks = []; for (let chunkSize = 1024; chunkSize <= 1024 * 1024; chunkSize *= 2) { chunks.push(largeData.slice(0, chunkSize)); } largeData = chunks.join(""); const stream = new ReadableStream({ start(controller) { for (let chunk of chunks) { controller.enqueue(chunk); } controller.close(); }, }); const request = new Request("https://example.com", { method: "POST", body: stream }); const clonedRequest = request.clone(); const originalBody = await request.text(); const clonedBody = await clonedRequest.text(); expect(originalBody).toBe(largeData); expect(clonedBody).toBe(largeData); }); test("Request with large streaming body can be cloned (pull)", async () => { let largeData = "x".repeat(1024 * 1024); // 1MB of data let chunks = []; for (let chunkSize = 1024; chunkSize <= 1024 * 1024; chunkSize *= 2) { chunks.push(largeData.slice(0, chunkSize)); } largeData = chunks.join(""); const stream = new ReadableStream({ async pull(controller) { await 42; for (let chunk of chunks) { controller.enqueue(chunk); } controller.close(); }, }); const request = new Request("https://example.com", { method: "POST", body: stream }); const clonedRequest = request.clone(); const originalBody = await request.text(); const clonedBody = await clonedRequest.text(); expect(originalBody).toBe(largeData); expect(clonedBody).toBe(largeData); }); test("Response with chunked streaming body can be cloned", async () => { const chunks = ["Chunk1", "Chunk2", "Chunk3"]; const stream = new ReadableStream({ async start(controller) { for (const chunk of chunks) { controller.enqueue(chunk); await new Promise(resolve => setTimeout(resolve, 10)); } controller.close(); }, }); const response = new Response(stream); const clonedResponse = response.clone(); const originalBody = await response.text(); const clonedBody = await clonedResponse.text(); expect(originalBody).toBe(chunks.join("")); expect(clonedBody).toBe(chunks.join("")); }); test("Request with streaming body can be cloned multiple times", async () => { const stream = new ReadableStream({ start(controller) { controller.enqueue("Multi"); controller.enqueue("Clone"); controller.enqueue("Test"); controller.close(); }, }); const request = new Request("https://example.com", { method: "POST", body: stream }); const clonedRequest1 = request.clone(); const clonedRequest2 = request.clone(); const originalBody = await request.text(); const clonedBody1 = await clonedRequest1.text(); const clonedBody2 = await clonedRequest2.text(); expect(originalBody).toBe("MultiCloneTest"); expect(clonedBody1).toBe("MultiCloneTest"); expect(clonedBody2).toBe("MultiCloneTest"); }); test("Request with string body can be cloned", async () => { const body = "Hello, world!"; const request = new Request("https://example.com", { method: "POST", body }); const clonedRequest = request.clone(); const originalBody = await request.text(); const clonedBody = await clonedRequest.text(); expect(originalBody).toBe(body); expect(clonedBody).toBe(body); }); test("Response with string body can be cloned", async () => { const body = "Hello, world!"; const response = new Response(body); const clonedResponse = response.clone(); const originalBody = await response.text(); const clonedBody = await clonedResponse.text(); expect(originalBody).toBe(body); expect(clonedBody).toBe(body); }); test("Request with ArrayBuffer body can be cloned", async () => { const body = new ArrayBuffer(8); new Uint8Array(body).set([1, 2, 3, 4, 5, 6, 7, 8]); const request = new Request("https://example.com", { method: "POST", body }); const clonedRequest = request.clone(); const originalBody = new Uint8Array(await request.arrayBuffer()); const clonedBody = new Uint8Array(await clonedRequest.arrayBuffer()); expect(originalBody).toEqual(new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8])); expect(clonedBody).toEqual(new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8])); }); test("Response with ArrayBuffer body can be cloned", async () => { const body = new ArrayBuffer(8); new Uint8Array(body).set([1, 2, 3, 4, 5, 6, 7, 8]); const response = new Response(body); const clonedResponse = response.clone(); const originalBody = new Uint8Array(await response.arrayBuffer()); const clonedBody = new Uint8Array(await clonedResponse.arrayBuffer()); expect(originalBody).toEqual(new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8])); expect(clonedBody).toEqual(new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8])); }); test("Request with Uint8Array body can be cloned", async () => { const body = new Uint8Array([1, 2, 3, 4, 5]); const request = new Request("https://example.com", { method: "POST", body }); const clonedRequest = request.clone(); const originalBody = new Uint8Array(await request.arrayBuffer()); const clonedBody = new Uint8Array(await clonedRequest.arrayBuffer()); expect(originalBody).toEqual(new Uint8Array([1, 2, 3, 4, 5])); expect(clonedBody).toEqual(new Uint8Array([1, 2, 3, 4, 5])); }); test("Response with Uint8Array body can be cloned", async () => { const body = new Uint8Array([1, 2, 3, 4, 5]); const response = new Response(body); const clonedResponse = response.clone(); const originalBody = new Uint8Array(await response.arrayBuffer()); const clonedBody = new Uint8Array(await clonedResponse.arrayBuffer()); expect(originalBody).toEqual(new Uint8Array([1, 2, 3, 4, 5])); expect(clonedBody).toEqual(new Uint8Array([1, 2, 3, 4, 5])); }); test("Request with mixed body types can be cloned", async () => { const bodies = [ "Hello, world!", new ArrayBuffer(8), new Uint8Array([1, 2, 3, 4, 5]), new ReadableStream({ start(controller) { controller.enqueue("Stream"); controller.close(); }, }), ]; for (const body of bodies) { const request = new Request("https://example.com", { method: "POST", body }); const clonedRequest = request.clone(); let originalBody, clonedBody; if (typeof body === "string") { originalBody = await request.text(); clonedBody = await clonedRequest.text(); } else { originalBody = new Uint8Array(await request.arrayBuffer()); clonedBody = new Uint8Array(await clonedRequest.arrayBuffer()); } expect(originalBody).toEqual(clonedBody); } }); test("Response with mixed body types can be cloned", async () => { const bodies = [ "Hello, world!", new ArrayBuffer(8), new Uint8Array([1, 2, 3, 4, 5]), new ReadableStream({ start(controller) { controller.enqueue("Stream"); controller.close(); }, }), ]; for (const body of bodies) { const response = new Response(body); const clonedResponse = response.clone(); let originalBody, clonedBody; if (typeof body === "string") { originalBody = await response.text(); clonedBody = await clonedResponse.text(); } else { originalBody = new Uint8Array(await response.arrayBuffer()); clonedBody = new Uint8Array(await clonedResponse.arrayBuffer()); } expect(originalBody).toEqual(clonedBody); } }); test("Request with non-ASCII string body can be cloned", async () => { const body = "Hello, 世界! 🌍 Здравствуй, мир!"; const request = new Request("https://example.com", { method: "POST", body }); const clonedRequest = request.clone(); const originalBody = await request.text(); const clonedBody = await clonedRequest.text(); expect(originalBody).toBe(body); expect(clonedBody).toBe(body); }); test("Response with non-ASCII string body can be cloned", async () => { const body = "こんにちは、世界! 🌎 Bonjour, le monde!"; const response = new Response(body); const clonedResponse = response.clone(); const originalBody = await response.text(); const clonedBody = await clonedResponse.text(); expect(originalBody).toBe(body); expect(clonedBody).toBe(body); }); test("Request with streaming non-ASCII body can be cloned", async () => { const stream = new ReadableStream({ start(controller) { controller.enqueue("Hello, "); controller.enqueue("世界"); controller.enqueue("! 🌏 "); controller.enqueue("Olá, mundo!"); controller.close(); }, }); const request = new Request("https://example.com", { method: "POST", body: stream }); const clonedRequest = request.clone(); const originalBody = await request.text(); const clonedBody = await clonedRequest.text(); expect(originalBody).toBe("Hello, 世界! 🌏 Olá, mundo!"); expect(clonedBody).toBe("Hello, 世界! 🌏 Olá, mundo!"); }); test("Response with streaming non-ASCII body can be cloned", async () => { const stream = new ReadableStream({ start(controller) { controller.enqueue("Здравствуй, "); controller.enqueue("мир"); controller.enqueue("! 🌍 "); controller.enqueue("Hola, mundo!"); controller.close(); }, }); const response = new Response(stream); const clonedResponse = response.clone(); const originalBody = await response.text(); const clonedBody = await clonedResponse.text(); expect(originalBody).toBe("Здравствуй, мир! 🌍 Hola, mundo!"); expect(clonedBody).toBe("Здравствуй, мир! 🌍 Hola, mundo!"); }); test("Request with mixed non-ASCII body types can be cloned", async () => { const bodies = [ "Hello, 世界! 🌍", new TextEncoder().encode("こんにちは、世界! 🌎"), new ReadableStream({ start(controller) { controller.enqueue("Здравствуй, "); controller.enqueue("мир"); controller.enqueue("! 🌏"); controller.close(); }, }), ]; for (const body of bodies) { const request = new Request("https://example.com", { method: "POST", body }); const clonedRequest = request.clone(); let originalBody, clonedBody; if (typeof body === "string") { originalBody = await request.text(); clonedBody = await clonedRequest.text(); } else if (body instanceof Uint8Array) { originalBody = new TextDecoder().decode(await request.arrayBuffer()); clonedBody = new TextDecoder().decode(await clonedRequest.arrayBuffer()); } else { originalBody = await request.text(); clonedBody = await clonedRequest.text(); } expect(originalBody).toEqual(clonedBody); } }); test("ReadableStream with mixed content (starting with string) can be converted to text", async () => { const mixedContent = [ "Hello, 世界! 🌍", new Uint8Array([240, 159, 140, 141]), // 🌍 emoji new ArrayBuffer(4), "Здравствуй, мир!", ]; let index = 0; const stream = new ReadableStream({ async pull(controller) { await 1; // Delay in a microtask if (index < mixedContent.length) { controller.enqueue(mixedContent[index++]); } else { controller.close(); } }, }); const text = await stream.text(); expect(typeof text).toBe("string"); expect(text).toContain("Hello, 世界!"); expect(text).toContain("🌍"); expect(text).toContain("Здравствуй, мир!"); }); test("ReadableStream with mixed content (starting with Uint8Array) can be converted to ArrayBuffer", async () => { const mixedContent = [ new Uint8Array([72, 101, 108, 108, 111]), // "Hello" in ASCII "世界! 🌍", new ArrayBuffer(4), "Здравствуй, мир!", ]; let index = 0; const stream = new ReadableStream({ async pull(controller) { await 1; // Delay in a microtask if (index < mixedContent.length) { controller.enqueue(mixedContent[index++]); } else { controller.close(); } }, }); const arrayBuffer = await Bun.readableStreamToArrayBuffer(stream); expect(arrayBuffer).toBeInstanceOf(ArrayBuffer); const text = new TextDecoder().decode(arrayBuffer); expect(text).toContain("Hello"); expect(text).toContain("世界!"); expect(text).toContain("🌍"); expect(text).toContain("Здравствуй, мир!"); }); test("ReadableStream with mixed content (starting with ArrayBuffer) can be converted to Uint8Array", async () => { const mixedContent = [ new ArrayBuffer(4), "Hello, 世界! 🌍", new Uint8Array([240, 159, 140, 141]), // 🌍 emoji "Здравствуй, мир!", ]; let index = 0; const stream = new ReadableStream({ async pull(controller) { await 1; // Delay in a microtask if (index < mixedContent.length) { controller.enqueue(mixedContent[index++]); } else { controller.close(); } }, }); const uint8Array = await Bun.readableStreamToBytes(stream); expect(uint8Array).toBeInstanceOf(Uint8Array); const text = new TextDecoder().decode(uint8Array); expect(text).toContain("Hello, 世界!"); expect(text).toContain("🌍"); expect(text).toContain("Здравствуй, мир!"); }); test("ReadableStream with mixed content (starting with string) can be converted to ArrayBuffer using Response", async () => { const mixedContent = [ "Hello, ", "世界! ", new Uint8Array([240, 159, 140, 141]), // 🌍 emoji "Здравствуй, мир!", ]; let index = 0; const stream = new ReadableStream({ async pull(controller) { await 1; // Delay in a microtask if (index < mixedContent.length) { controller.enqueue(mixedContent[index++]); } else { controller.close(); } }, }); const response = new Response(stream); const arrayBuffer = await response.arrayBuffer(); expect(arrayBuffer).toBeInstanceOf(ArrayBuffer); const text = new TextDecoder().decode(arrayBuffer); expect(text).toContain("Hello"); expect(text).toContain("世界!"); expect(text).toContain("🌍"); expect(text).toContain("Здравствуй, мир!"); }); test("ReadableStream with mixed content (starting with ArrayBuffer) can be converted to Uint8Array using Response", async () => { const mixedContent = [ new ArrayBuffer(4), "Hello, 世界! 🌍", new Uint8Array([240, 159, 140, 141]), // 🌍 emoji "Здравствуй, мир!", ]; let index = 0; const stream = new ReadableStream({ async pull(controller) { await 1; // Delay in a microtask if (index < mixedContent.length) { controller.enqueue(mixedContent[index++]); } else { controller.close(); } }, }); const response = new Response(stream); const uint8Array = await response.bytes(); expect(uint8Array).toBeInstanceOf(Uint8Array); const text = new TextDecoder().decode(uint8Array); expect(text).toStartWith("\0\0\0\0"); expect(text).toContain("Hello, 世界!"); expect(text).toContain("🌍"); expect(text).toContain("Здравствуй, мир!"); });