diff options
author | 2023-03-07 12:22:34 -0800 | |
---|---|---|
committer | 2023-03-07 12:22:34 -0800 | |
commit | f7e4eb83694aa007a492ef66c28ffbe6a2dae791 (patch) | |
tree | 7af25aa5c42a2e1b2b47ba1df35f8caa9054cbeb /test/js/third_party/react-dom/react-dom.test.tsx | |
parent | 36275a44ce7a33587bd26aad120042ab95470ff3 (diff) | |
download | bun-f7e4eb83694aa007a492ef66c28ffbe6a2dae791.tar.gz bun-f7e4eb83694aa007a492ef66c28ffbe6a2dae791.tar.zst bun-f7e4eb83694aa007a492ef66c28ffbe6a2dae791.zip |
Reorganize tests (#2332)
Diffstat (limited to 'test/js/third_party/react-dom/react-dom.test.tsx')
-rw-r--r-- | test/js/third_party/react-dom/react-dom.test.tsx | 285 |
1 files changed, 285 insertions, 0 deletions
diff --git a/test/js/third_party/react-dom/react-dom.test.tsx b/test/js/third_party/react-dom/react-dom.test.tsx new file mode 100644 index 000000000..2f1309fb8 --- /dev/null +++ b/test/js/third_party/react-dom/react-dom.test.tsx @@ -0,0 +1,285 @@ +import { + concatArrayBuffers, + readableStreamToArray, + readableStreamToArrayBuffer, + readableStreamToBlob, + readableStreamToText, + serve, +} from "bun"; +import { heapStats } from "bun:jsc"; +import { describe, expect, it } from "bun:test"; +import { renderToReadableStream as renderToReadableStreamBrowser } from "react-dom/server.browser"; +import { gc } from "harness"; +import { renderToReadableStream as renderToReadableStreamBun } from "./react-dom-server.bun.cjs"; +import React from "react"; + +Object.defineProperty(renderToReadableStreamBrowser, "name", { + value: "server.browser", +}); +Object.defineProperty(renderToReadableStreamBun, "name", { + value: "server.bun", +}); +var port = 8908; + +const fixtures = [ + // Needs at least six variations + // - < 8 chars, latin1 + // - 8+ chars, latin1 + // - 16+ chars, latin1 + // - < 8 chars, utf16 + // - 8+ chars, utf16 + // - 16+ chars, utf16 + ["<a>b</a>", <a>b</a>], + ["<span>Hello World!</span>", <span>Hello World!</span>], + ["<a></a>", <a />], + ["<span>π</span>", <span>π</span>], + ["<a>π</a>", <a>π</a>], + ["<span>Hello World! π</span>", <span>Hello World! π</span>], + [ + "<span>Hello World!</span>π", + <> + <span>Hello World!</span>π + </>, + ], + [ + "<span>πHello World!</span>", + <> + <span>πHello World!</span> + </>, + ], + ["π", <>π</>], + ["lπl", <>lπl</>], + ["loπ", <>loπ</>], + ["πlo", <>πlo</>], + [ + "π<span>Hello World!</span>", + <> + π + <span>Hello World!</span> + </>, + ], + [ + "ππππ<span>Hello World!</span>", + <> + ππππ + <span>Hello World!</span> + </>, + ], + ["<span>HelloππππWorld!</span>", <span>HelloππππWorld!</span>], + [ + "<span>Hello World!</span>ππππ", + <> + <span>Hello World!</span> + ππππ + </>, + ], + [ + "πLπlπLπ<span>Alternating latin1 & utf16</span>", + <> + πLπlπLπ<span>Alternating latin1 & utf16</span> + </>, + ], + ["<span>HelloπLπlπLπWorld!</span>", <span>HelloπLπlπLπWorld!</span>], + [ + "<span>Hello World!</span>πLπlπLπ", + <> + <span>Hello World!</span> + πLπlπLπ + </>, + ], +]; + +describe("React", () => { + it("React.createContext works", () => { + expect(typeof React.createContext).toBe("function"); + const pleaseDontThrow = React.createContext({ foo: true }); + expect((pleaseDontThrow as any).$$typeof.description).toBe("react.context"); + + const pleaseDontThrow2 = (React as any).default.createContext({ + foo: true, + }); + expect(pleaseDontThrow2.$$typeof.description).toBe("react.context"); + }); +}); + +describe("ReactDOM", () => { + for (let renderToReadableStream of [renderToReadableStreamBun, renderToReadableStreamBrowser]) { + for (let [inputString, reactElement] of fixtures) { + describe(`${renderToReadableStream.name}(${inputString})`, () => { + it("Response.text()", async () => { + const stream = await renderToReadableStream(reactElement); + gc(); + const response = new Response(stream); + gc(); + try { + const text = await response.text(); + gc(); + expect(text.replaceAll("<!-- -->", "")).toBe(inputString); + gc(); + } catch (e: any) { + console.log(e.stack); + throw e; + } + }); + it("Response.arrayBuffer()", async () => { + const stream = await renderToReadableStream(reactElement); + gc(); + const response = new Response(stream); + gc(); + const text = new TextDecoder().decode(await response.arrayBuffer()); + gc(); + expect(text.replaceAll("<!-- -->", "")).toBe(inputString); + gc(); + }); + it("Response.blob()", async () => { + const stream = await renderToReadableStream(reactElement); + gc(); + const response = new Response(stream); + gc(); + const text = await (await response.blob()).text(); + gc(); + expect(text.replaceAll("<!-- -->", "")).toBe(inputString); + gc(); + }); + it("readableStreamToText(stream)", async () => { + const stream = await renderToReadableStream(reactElement); + gc(); + const text = await readableStreamToText(stream); + gc(); + expect(text.replaceAll("<!-- -->", "")).toBe(inputString); + gc(); + }); + it("readableStreamToBlob(stream)", async () => { + try { + const stream = await renderToReadableStream(reactElement); + gc(); + const blob = await readableStreamToBlob(stream); + const text = await blob.text(); + gc(); + expect(text.replaceAll("<!-- -->", "")).toBe(inputString); + gc(); + } catch (e: any) { + console.error(e.message); + console.error(e.stack); + throw e; + } + }); + it("readableStreamToArray(stream)", async () => { + const stream = await renderToReadableStream(reactElement); + gc(); + const array = await readableStreamToArray(stream); + const text = + renderToReadableStream === renderToReadableStreamBun + ? array.join("") + : new TextDecoder().decode(concatArrayBuffers(array as any[])); + gc(); + expect(text.replaceAll("<!-- -->", "")).toBe(inputString); + gc(); + }); + it("readableStreamToArrayBuffer(stream)", async () => { + const stream = await renderToReadableStream(reactElement); + gc(); + const arrayBuffer = await readableStreamToArrayBuffer(stream); + const text = new TextDecoder().decode(arrayBuffer); + gc(); + expect(text.replaceAll("<!-- -->", "")).toBe(inputString); + gc(); + }); + it("for await (chunk of stream)", async () => { + const stream = await renderToReadableStream(reactElement); + gc(); + const chunks: any = []; + for await (let chunk of stream) { + chunks.push(chunk); + } + const text = await new Response(chunks).text(); + gc(); + expect(text.replaceAll("<!-- -->", "")).toBe(inputString); + gc(); + }); + + it("for await (chunk of stream) (arrayBuffer)", async () => { + const stream = await renderToReadableStream(reactElement); + gc(); + const chunks: any[] = []; + for await (let chunk of stream) { + chunks.push(chunk); + } + const text = new TextDecoder().decode(await new Response(chunks as any).arrayBuffer()); + gc(); + expect(text.replaceAll("<!-- -->", "")).toBe(inputString); + gc(); + }); + }); + } + } + for (let renderToReadableStream of [renderToReadableStreamBun, renderToReadableStreamBrowser]) { + // there is an event loop bug that causes deadlocks + // the bug is with `fetch`, not with the HTTP server + for (let [inputString, reactElement] of fixtures) { + describe(`${renderToReadableStream.name}(${inputString})`, () => { + it("http server, 1 request", async () => { + await (async function () { + var server; + try { + server = serve({ + port: port++, + async fetch(req) { + return new Response(await renderToReadableStream(reactElement)); + }, + }); + const resp = await fetch("http://localhost:" + server.port + "/"); + expect((await resp.text()).replaceAll("<!-- -->", "")).toBe(inputString); + gc(); + } catch (e) { + throw e; + } finally { + server?.stop(); + gc(); + } + })(); + gc(); + expect(heapStats().objectTypeCounts.ReadableHTTPResponseSinkController ?? 0).toBe(1); + }); + const count = 4; + it(`http server, ${count} requests`, async () => { + var remain = count; + await (async function () { + var server; + try { + server = serve({ + port: port++, + async fetch(req) { + return new Response(await renderToReadableStream(reactElement)); + }, + }); + gc(); + while (remain--) { + var attempt = remain + 1; + const response = await fetch("http://localhost:" + server.port + "/"); + gc(); + const result = await response.text(); + try { + expect(result.replaceAll("<!-- -->", "")).toBe(inputString); + } catch (e: any) { + e.message += "\nAttempt: " + attempt; + throw e; + } + + gc(); + } + } catch (e) { + throw e; + } finally { + server.stop(); + } + })(); + + const { ReadableHTTPResponseSinkController = 0 } = heapStats().objectTypeCounts; + expect(ReadableHTTPResponseSinkController).toBe(1); + expect(remain + 1).toBe(0); + }); + }); + } + } +}); |