Skip to content

Commit fb53180

Browse files
Refactor incremental render tests to use jest mock functions for sink handling
1 parent 703133f commit fb53180

File tree

1 file changed

+45
-47
lines changed

1 file changed

+45
-47
lines changed

react_on_rails_pro/packages/node-renderer/tests/incrementalRender.test.ts

Lines changed: 45 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -56,19 +56,17 @@ describe('incremental render NDJSON endpoint', () => {
5656
});
5757

5858
const createMockSink = () => {
59-
const sinkAddCalls: unknown[] = [];
59+
const sinkAdd = jest.fn();
6060
const sinkEnd = jest.fn();
6161
const sinkAbort = jest.fn();
6262

6363
const sink: incremental.IncrementalRenderSink = {
64-
add: (chunk) => {
65-
sinkAddCalls.push(chunk);
66-
},
64+
add: sinkAdd,
6765
end: sinkEnd,
6866
abort: sinkAbort,
6967
};
7068

71-
return { sink, sinkAddCalls, sinkEnd, sinkAbort };
69+
return { sink, sinkAdd, sinkEnd, sinkAbort };
7270
};
7371

7472
const createMockResponse = (data = 'mock response'): ResponseResult => ({
@@ -120,7 +118,7 @@ describe('incremental render NDJSON endpoint', () => {
120118
const createBasicTestSetup = async () => {
121119
await createVmBundle(TEST_NAME);
122120

123-
const { sink, sinkAddCalls, sinkEnd, sinkAbort } = createMockSink();
121+
const { sink, sinkAdd, sinkEnd, sinkAbort } = createMockSink();
124122
const mockResponse = createMockResponse();
125123
const mockResult = createMockResult(sink, mockResponse);
126124

@@ -132,7 +130,7 @@ describe('incremental render NDJSON endpoint', () => {
132130

133131
return {
134132
sink,
135-
sinkAddCalls,
133+
sinkAdd,
136134
sinkEnd,
137135
sinkAbort,
138136
mockResponse,
@@ -155,14 +153,10 @@ describe('incremental render NDJSON endpoint', () => {
155153
},
156154
});
157155

158-
const processedChunks: unknown[] = [];
159156
const sinkAdd = jest.fn();
160157

161158
const sink: incremental.IncrementalRenderSink = {
162-
add: (chunk) => {
163-
processedChunks.push(chunk);
164-
sinkAdd(chunk);
165-
},
159+
add: sinkAdd,
166160
end: jest.fn(),
167161
abort: jest.fn(),
168162
};
@@ -186,7 +180,6 @@ describe('incremental render NDJSON endpoint', () => {
186180

187181
return {
188182
responseStream,
189-
processedChunks,
190183
sinkAdd,
191184
sink,
192185
mockResponse,
@@ -251,8 +244,7 @@ describe('incremental render NDJSON endpoint', () => {
251244
});
252245

253246
test('calls handleIncrementalRenderRequest immediately after first chunk and processes each subsequent chunk immediately', async () => {
254-
const { sinkAddCalls, sinkEnd, sinkAbort, handleSpy, SERVER_BUNDLE_TIMESTAMP } =
255-
await createBasicTestSetup();
247+
const { sinkAdd, sinkEnd, sinkAbort, handleSpy, SERVER_BUNDLE_TIMESTAMP } = await createBasicTestSetup();
256248

257249
// Create the HTTP request
258250
const req = createHttpRequest(SERVER_BUNDLE_TIMESTAMP);
@@ -271,7 +263,7 @@ describe('incremental render NDJSON endpoint', () => {
271263

272264
// Verify handleIncrementalRenderRequest was called immediately after first chunk
273265
expect(handleSpy).toHaveBeenCalledTimes(1);
274-
expect(sinkAddCalls).toHaveLength(0); // No subsequent chunks processed yet
266+
expect(sinkAdd).not.toHaveBeenCalled(); // No subsequent chunks processed yet
275267

276268
// Send subsequent props chunks one by one and verify immediate processing
277269
const chunksToSend = [{ a: 1 }, { b: 2 }, { c: 3 }];
@@ -280,16 +272,16 @@ describe('incremental render NDJSON endpoint', () => {
280272
const expectedCallsBeforeWrite = index;
281273

282274
// Verify state before writing this chunk
283-
expect(sinkAddCalls).toHaveLength(expectedCallsBeforeWrite);
275+
expect(sinkAdd).toHaveBeenCalledTimes(expectedCallsBeforeWrite);
284276

285277
// Wait for the chunk to be processed
286278
await waitFor(() => {
287-
expect(sinkAddCalls).toHaveLength(expectedCallsBeforeWrite + 1);
279+
expect(sinkAdd).toHaveBeenCalledTimes(expectedCallsBeforeWrite + 1);
288280
});
289281

290282
// Verify the chunk was processed immediately
291-
expect(sinkAddCalls).toHaveLength(expectedCallsBeforeWrite + 1);
292-
expect(sinkAddCalls[expectedCallsBeforeWrite]).toEqual(chunk);
283+
expect(sinkAdd).toHaveBeenCalledTimes(expectedCallsBeforeWrite + 1);
284+
expect(sinkAdd).toHaveBeenNthCalledWith(expectedCallsBeforeWrite + 1, chunk);
293285
});
294286

295287
req.end();
@@ -304,7 +296,7 @@ describe('incremental render NDJSON endpoint', () => {
304296

305297
// Final verification: all chunks were processed in the correct order
306298
expect(handleSpy).toHaveBeenCalledTimes(1);
307-
expect(sinkAddCalls).toEqual([{ a: 1 }, { b: 2 }, { c: 3 }]);
299+
expect(sinkAdd.mock.calls).toEqual([[{ a: 1 }], [{ b: 2 }], [{ c: 3 }]]);
308300

309301
// Verify stream lifecycle methods were called correctly
310302
expect(sinkEnd).toHaveBeenCalledTimes(1);
@@ -362,7 +354,7 @@ describe('incremental render NDJSON endpoint', () => {
362354
// Create a bundle for this test
363355
await createVmBundle(TEST_NAME);
364356

365-
const { sink, sinkAddCalls, sinkEnd, sinkAbort } = createMockSink();
357+
const { sink, sinkAdd, sinkEnd, sinkAbort } = createMockSink();
366358

367359
const mockResponse: ResponseResult = createMockResponse();
368360

@@ -385,31 +377,31 @@ describe('incremental render NDJSON endpoint', () => {
385377
const initialObj = createInitialObject(SERVER_BUNDLE_TIMESTAMP);
386378
req.write(`${JSON.stringify(initialObj)}\n`);
387379

388-
// Wait for the server to process the first object and set up the response
380+
// Wait for the server to process the first object
389381
await waitFor(() => {
390382
expect(handleSpy).toHaveBeenCalledTimes(1);
391383
});
392384

393-
// Verify handleIncrementalRenderRequest was called
394-
expect(handleSpy).toHaveBeenCalledTimes(1);
395-
396-
// Send a valid update chunk
397-
req.write(`${JSON.stringify({ a: 1 })}\n`);
385+
// Send a valid chunk first
386+
const validChunk = { a: 1 };
387+
req.write(`${JSON.stringify(validChunk)}\n`);
398388

399389
// Wait for processing
400390
await waitFor(() => {
401-
expect(sinkAddCalls).toHaveLength(1);
391+
expect(sinkAdd).toHaveBeenCalledWith({ a: 1 });
402392
});
403393

404394
// Verify the valid chunk was processed
405-
expect(sinkAddCalls).toHaveLength(1);
406-
expect(sinkAddCalls[0]).toEqual({ a: 1 });
395+
expect(sinkAdd).toHaveBeenCalledWith({ a: 1 });
407396

408397
// Send a malformed JSON chunk
409-
req.write('{"b": 2, "c": 3\n'); // Missing closing brace
398+
const malformedChunk = '{"invalid": json}\n';
399+
req.write(malformedChunk);
400+
401+
// Send another valid chunk
402+
const secondValidChunk = { d: 4 };
403+
req.write(`${JSON.stringify(secondValidChunk)}\n`);
410404

411-
// Send another valid chunk after the malformed one
412-
req.write(`${JSON.stringify({ d: 4 })}\n`);
413405
req.end();
414406

415407
// Wait for the request to complete
@@ -422,10 +414,9 @@ describe('incremental render NDJSON endpoint', () => {
422414

423415
// Verify that processing continued after the malformed chunk
424416
// The malformed chunk should be skipped, but valid chunks should be processed
425-
426417
// Verify that the stream completed successfully
427418
await waitFor(() => {
428-
expect(sinkAddCalls).toEqual([{ a: 1 }, { d: 4 }]);
419+
expect(sinkAdd.mock.calls).toEqual([[{ a: 1 }], [{ d: 4 }]]);
429420
expect(sinkEnd).toHaveBeenCalledTimes(1);
430421
expect(sinkAbort).not.toHaveBeenCalled();
431422
});
@@ -435,7 +426,7 @@ describe('incremental render NDJSON endpoint', () => {
435426
// Create a bundle for this test
436427
await createVmBundle(TEST_NAME);
437428

438-
const { sink, sinkAddCalls, sinkEnd } = createMockSink();
429+
const { sink, sinkAdd, sinkEnd } = createMockSink();
439430

440431
const mockResponse: ResponseResult = createMockResponse();
441432

@@ -454,7 +445,7 @@ describe('incremental render NDJSON endpoint', () => {
454445
// Set up promise to handle the response
455446
const responsePromise = setupResponseHandler(req);
456447

457-
// Write first object
448+
// Write first object (valid JSON)
458449
const initialObj = createInitialObject(SERVER_BUNDLE_TIMESTAMP);
459450
req.write(`${JSON.stringify(initialObj)}\n`);
460451

@@ -464,12 +455,16 @@ describe('incremental render NDJSON endpoint', () => {
464455
});
465456

466457
// Send chunks with empty lines mixed in
467-
req.write('\n'); // Empty line
468-
req.write(`${JSON.stringify({ a: 1 })}\n`);
469-
req.write('\n'); // Empty line
470-
req.write(`${JSON.stringify({ b: 2 })}\n`);
471-
req.write('\n'); // Empty line
472-
req.write(`${JSON.stringify({ c: 3 })}\n`);
458+
const chunksToSend = [{ a: 1 }, { b: 2 }, { c: 3 }];
459+
460+
for (const chunk of chunksToSend) {
461+
req.write(`${JSON.stringify(chunk)}\n`);
462+
// eslint-disable-next-line no-await-in-loop
463+
await waitFor(() => {
464+
expect(sinkAdd).toHaveBeenCalledWith(chunk);
465+
});
466+
}
467+
473468
req.end();
474469

475470
// Wait for the request to complete
@@ -482,7 +477,7 @@ describe('incremental render NDJSON endpoint', () => {
482477

483478
// Verify that only valid JSON objects were processed
484479
expect(handleSpy).toHaveBeenCalledTimes(1);
485-
expect(sinkAddCalls).toEqual([{ a: 1 }, { b: 2 }, { c: 3 }]);
480+
expect(sinkAdd.mock.calls).toEqual([[{ a: 1 }], [{ b: 2 }], [{ c: 3 }]]);
486481
expect(sinkEnd).toHaveBeenCalledTimes(1);
487482
});
488483

@@ -530,7 +525,7 @@ describe('incremental render NDJSON endpoint', () => {
530525
'Goodbye from stream',
531526
];
532527

533-
const { responseStream, processedChunks, sinkAdd, sink, handleSpy, SERVER_BUNDLE_TIMESTAMP } =
528+
const { responseStream, sinkAdd, sink, handleSpy, SERVER_BUNDLE_TIMESTAMP } =
534529
await createStreamingTestSetup();
535530

536531
// write the response chunks to the stream
@@ -595,7 +590,10 @@ describe('incremental render NDJSON endpoint', () => {
595590
});
596591

597592
// Verify that all request chunks were processed
598-
expect(processedChunks).toEqual(chunksToSend);
593+
expect(sinkAdd).toHaveBeenCalledTimes(chunksToSend.length);
594+
chunksToSend.forEach((chunk, index) => {
595+
expect(sinkAdd).toHaveBeenNthCalledWith(index + 1, chunk);
596+
});
599597

600598
// Verify that the mock was called correctly
601599
expect(handleSpy).toHaveBeenCalledTimes(1);

0 commit comments

Comments
 (0)