Skip to content

Commit

Permalink
test: add serialization test
Browse files Browse the repository at this point in the history
  • Loading branch information
damassi committed Nov 24, 2024
1 parent 6f9a1ad commit 112329a
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 22 deletions.
21 changes: 13 additions & 8 deletions src/System/Router/Utils/__tests__/renderToStream.jest.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ describe("renderToStream", () => {
const res = ({
statusCode: 0,
setHeader: jest.fn(),
res: { write: jest.fn(), end: jest.fn() },
} as unknown) as ArtsyResponse

const sheet = ({
Expand Down Expand Up @@ -109,7 +110,7 @@ describe("renderToStream", () => {
const jsx = <div>Timeout Test</div>
renderToStream({ jsx, sheet, res })

jest.advanceTimersByTime(5000)
jest.advanceTimersByTime(10000) // stream timeout

expect(mockAbort).toHaveBeenCalled()
jest.useRealTimers()
Expand Down Expand Up @@ -142,6 +143,8 @@ describe("renderToStream", () => {
)
})

await flushPromiseQueue()

stream.end()
})

Expand All @@ -161,20 +164,22 @@ describe("renderToStream", () => {

const stream = renderToStream({ jsx, sheet, res })

stream.write("<html><head></head><body></body></html>")
stream.write("<html><head></head><body>")

const chunks: string[] = []
stream.on("data", chunk => {
chunks.push(chunk)
})

await new Promise(resolve => {
stream.on("end", resolve)
stream.on("end", () => {
const result = chunks.join("")
expect(result).toContain(
'<html><head>mock-css</head><body><div class="content">Hello World</div>'
)
})

const result = chunks.join("")
expect(result).toContain(
'<html><head>mock-css</head><body></body></html><div class="content">Hello World</div>'
)
await flushPromiseQueue()

stream.end()
})
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import { SSRCache } from "react-relay-network-modern-ssr/lib/server"
import { serializeRelayHydrationData } from "System/Router/Utils/serializeRelayHydrationData"
import mockSerialize from "serialize-javascript"

jest.mock("serialize-javascript", () => jest.fn())

describe("serializeRelayHydrationData", () => {
afterEach(() => {
jest.clearAllMocks()
})

it("should serialize the relay data correctly", () => {
const mockData = ([
[
{
id: 1,
_res: "some-network-response",
data: "value1",
},
{
id: 2,
_res: "another-response",
data: "value2",
},
],
] as unknown) as SSRCache

mockSerialize.mockImplementation((data, options) => JSON.stringify(data))

const result = serializeRelayHydrationData(mockData)

expect(mockSerialize).toHaveBeenCalledTimes(2)
expect(mockSerialize).toHaveBeenCalledWith(mockData, { isJSON: true })
expect(mockSerialize).toHaveBeenCalledWith(JSON.stringify(mockData), {
isJSON: true,
})

expect(result).toBe(JSON.stringify(JSON.stringify(mockData)))
expect(mockData[0][0]).not.toHaveProperty("_res")
expect(mockData[0][1]).not.toHaveProperty("_res")
})

it("should handle empty data gracefully", () => {
mockSerialize.mockImplementation((data, options) => JSON.stringify(data))

const result = serializeRelayHydrationData([])

expect(mockSerialize).toHaveBeenCalledTimes(2)
expect(mockSerialize).toHaveBeenCalledWith([], { isJSON: true })
expect(mockSerialize).toHaveBeenCalledWith(JSON.stringify([]), {
isJSON: true,
})

expect(result).toBe(JSON.stringify(JSON.stringify([])))
})

it("should return an empty serialized array when an error occurs", () => {
const mockData = ([
[
{
id: 1,
_res: "some-network-response",
data: "value1",
},
],
] as unknown) as SSRCache

mockSerialize.mockImplementation(() => {
throw new Error("Serialization Error")
})

expect(() => {
const result = serializeRelayHydrationData(mockData)
expect(mockSerialize).toHaveBeenCalledTimes(1)
expect(result).toBe(mockSerialize("[]", { isJSON: true }))
}).toThrowError("Serialization Error")
})
})
4 changes: 2 additions & 2 deletions src/System/Router/Utils/renderToStream.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { ArtsyResponse } from "Server/middleware/artsyExpress"
import { Transform } from "stream"
import { ServerStyleSheet } from "styled-components"

const STREAM_TIMEOUT = 5000
const STREAM_TIMEOUT_MS = 10000

interface RenderToStreamProps {
jsx: ReactNode
Expand Down Expand Up @@ -80,7 +80,7 @@ export const renderToStream = ({
// Abandon and switch to client rendering if enough time passes.
streamTimeout = setTimeout(() => {
abort()
}, STREAM_TIMEOUT)
}, STREAM_TIMEOUT_MS)

return stream
}
21 changes: 9 additions & 12 deletions src/System/Router/Utils/serializeRelayHydrationData.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,27 @@ import { RelayNetworkLayerResponse } from "react-relay-network-modern"
import { SSRCache } from "react-relay-network-modern-ssr/lib/server"
import serialize from "serialize-javascript"

export const serializeRelayHydrationData = (initialRelayData: SSRCache) => {
export const serializeRelayHydrationData = (
initialRelayData: SSRCache = []
): string => {
initialRelayData.forEach(entry => {
entry.forEach((item: RelayNetworkLayerResponse) => {
// Clean relay data of problematic data structures
delete item._res
delete item._res // Remove unnecessary relay network data
})
})

let hydrationData

try {
hydrationData = serialize(initialRelayData, {
// Double pass to ensure that the data is serialized correctly
// TODO: Fix this
return serialize(serialize(initialRelayData, { isJSON: true }), {
isJSON: true,
})
} catch (error) {
hydrationData = "{}"

console.error(
"[system/router/serializeRelayHydrationData] Error serializing data:",
error
)
}

return serialize(hydrationData || {}, {
isJSON: true,
})
return serialize("[]", { isJSON: true })
}
}

0 comments on commit 112329a

Please sign in to comment.