diff --git a/src/System/Router/Utils/__tests__/renderToStream.jest.tsx b/src/System/Router/Utils/__tests__/renderToStream.jest.tsx new file mode 100644 index 00000000000..a6c15c747ea --- /dev/null +++ b/src/System/Router/Utils/__tests__/renderToStream.jest.tsx @@ -0,0 +1,126 @@ +import { flushPromiseQueue } from "DevTools/flushPromiseQueue" +import { renderToPipeableStream } from "react-dom/server" +import { ArtsyResponse } from "Server/middleware/artsyExpress" +import { renderToStream } from "System/Router/Utils/renderToStream" + +jest.mock("react-dom/server", () => ({ + renderToPipeableStream: jest.fn(), +})) + +describe("renderToStream", () => { + const mockRenderToPipeableStream = renderToPipeableStream as jest.Mock + + const mockRes = ({ + statusCode: 0, + setHeader: jest.fn(), + } as unknown) as ArtsyResponse + + const mockSheet = { + _emitSheetCSS: jest.fn(() => "mock-css"), + instance: { + clearTag: jest.fn(), + }, + } + + afterEach(() => { + jest.clearAllMocks() + }) + + it("should set the response status and content type on shell ready", async () => { + const mockPipe = jest.fn() + const mockAbort = jest.fn() + + mockRenderToPipeableStream.mockImplementation((_, options) => { + setTimeout(() => { + options.onShellReady() + }) + + return { pipe: mockPipe, abort: mockAbort } + }) + + const jsx =
Hello World
+ renderToStream(jsx, mockSheet, mockRes) + + await flushPromiseQueue() + + expect(mockRes.statusCode).toBe(200) + expect(mockRes.setHeader).toHaveBeenCalledWith( + "Content-Type", + "text/html; charset=utf-8" + ) + expect(mockPipe).toHaveBeenCalled() + }) + + it("should handle onError and set didError to true", async () => { + const mockPipe = jest.fn() + const mockAbort = jest.fn() + + mockRenderToPipeableStream.mockImplementation((_, options) => { + options.onError(new Error("Test error")) + + setTimeout(() => { + options.onShellReady() + }) + + return { pipe: mockPipe, abort: mockAbort } + }) + + const jsx =
Hello Error
+ renderToStream(jsx, mockSheet, mockRes) + + await flushPromiseQueue() + + expect(mockRes.statusCode).toBe(500) + expect(mockPipe).toHaveBeenCalled() + }) + + it("should call abort if STREAM_TIMEOUT is reached", () => { + jest.useFakeTimers() + const mockAbort = jest.fn() + + mockRenderToPipeableStream.mockImplementation((_, options) => { + return { pipe: jest.fn(), abort: mockAbort } + }) + + const jsx =
Timeout Test
+ renderToStream(jsx, mockSheet, mockRes) + + jest.advanceTimersByTime(5000) + + expect(mockAbort).toHaveBeenCalled() + jest.useRealTimers() + }) + + // eslint-disable-next-line jest/no-done-callback + it("should transform the stream and inject CSS into the HTML", done => { + const mockPipe = jest.fn() + const mockAbort = jest.fn() + + mockRenderToPipeableStream.mockImplementation((_, options) => { + setTimeout(() => { + options.onShellReady() + }) + return { pipe: mockPipe, abort: mockAbort } + }) + + const jsx =
Stream Test
+ const stream = renderToStream(jsx, mockSheet, mockRes) + + stream.write("") + + const chunks: string[] = [] + stream.on("data", chunk => { + chunks.push(chunk) + }) + + stream.on("end", () => { + const result = chunks.join("") + expect(result).toContain( + "mock-css" + ) + done() + }) + + stream.end() + }) +}) diff --git a/src/System/Router/Utils/collectAssets.tsx b/src/System/Router/Utils/collectAssets.tsx index 54ff430f234..574904828e0 100644 --- a/src/System/Router/Utils/collectAssets.tsx +++ b/src/System/Router/Utils/collectAssets.tsx @@ -79,10 +79,6 @@ export const collectAssets = async ({ bundleScriptTags .split("\n") .map(script => { - /** - * In production, prefix injected script src with CDN endpoint. - * @see https://github.com/artsy/force/blob/main/src/lib/middleware/asset.ts#L23 - */ if (getENV("CDN_URL")) { const scriptTagWithCDN = script.replace( /src="\/assets/g,