Skip to content

Commit 4707677

Browse files
committed
fix: enhance tests for multi-instance component handling and stream status
1 parent 0bfba93 commit 4707677

1 file changed

Lines changed: 136 additions & 0 deletions

File tree

packages/x-markdown/src/XMarkdown/__tests__/Renderer.test.ts

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,142 @@ describe('Renderer', () => {
210210
createElementSpy.mockRestore();
211211
});
212212

213+
it('should handle multiple instances of the same component with correct streamStatus', () => {
214+
const components = {
215+
'multi-instance': MockComponent,
216+
};
217+
218+
const renderer = new Renderer({ components });
219+
const createElementSpy = jest.spyOn(React, 'createElement');
220+
221+
// Scenario: First instance is closed (done), second instance is open (loading)
222+
const html = '<multi-instance>Instance 1</multi-instance><multi-instance>Instance 2';
223+
renderer.processHtml(html);
224+
225+
// Filter calls to MockComponent
226+
const calls = createElementSpy.mock.calls.filter((call) => call[0] === MockComponent);
227+
228+
expect(calls.length).toBe(2);
229+
230+
// First instance should be done
231+
expect(calls[0][1]).toEqual(
232+
expect.objectContaining({
233+
streamStatus: 'done',
234+
}),
235+
);
236+
237+
// Second instance should be loading
238+
expect(calls[1][1]).toEqual(
239+
expect.objectContaining({
240+
streamStatus: 'loading',
241+
}),
242+
);
243+
244+
createElementSpy.mockRestore();
245+
});
246+
247+
it('should mark all instances as done when all are closed', () => {
248+
const components = {
249+
'multi-instance': MockComponent,
250+
};
251+
252+
const renderer = new Renderer({ components });
253+
const createElementSpy = jest.spyOn(React, 'createElement');
254+
255+
const html =
256+
'<multi-instance>Instance 1</multi-instance><multi-instance>Instance 2</multi-instance>';
257+
renderer.processHtml(html);
258+
259+
const calls = createElementSpy.mock.calls.filter((call) => call[0] === MockComponent);
260+
261+
expect(calls.length).toBe(2);
262+
expect(calls[0][1]).toEqual(expect.objectContaining({ streamStatus: 'done' }));
263+
expect(calls[1][1]).toEqual(expect.objectContaining({ streamStatus: 'done' }));
264+
265+
createElementSpy.mockRestore();
266+
});
267+
268+
it('should handle nested instances of the same component correctly', () => {
269+
const components = {
270+
'multi-instance': MockComponent,
271+
};
272+
273+
const renderer = new Renderer({ components });
274+
const createElementSpy = jest.spyOn(React, 'createElement');
275+
276+
// Outer open, Inner closed
277+
const html = '<multi-instance>Outer <multi-instance>Inner</multi-instance>';
278+
renderer.processHtml(html);
279+
280+
const calls = createElementSpy.mock.calls.filter((call) => call[0] === MockComponent);
281+
expect(calls.length).toBe(2);
282+
283+
// Inner instance (processed first as children are created before parent)
284+
expect(calls[0][1]).toEqual(expect.objectContaining({ streamStatus: 'done' }));
285+
// Outer instance
286+
expect(calls[1][1]).toEqual(expect.objectContaining({ streamStatus: 'loading' }));
287+
288+
createElementSpy.mockRestore();
289+
});
290+
291+
it('should handle deep nesting with mixed states', () => {
292+
const components = {
293+
'multi-instance': MockComponent,
294+
};
295+
296+
const renderer = new Renderer({ components });
297+
const createElementSpy = jest.spyOn(React, 'createElement');
298+
299+
// Level 1: Open
300+
// Level 2: Open
301+
// Level 3: Closed
302+
const html = '<multi-instance>1<multi-instance>2<multi-instance>3</multi-instance>';
303+
renderer.processHtml(html);
304+
305+
const calls = createElementSpy.mock.calls.filter((call) => call[0] === MockComponent);
306+
expect(calls.length).toBe(3);
307+
308+
// Level 3 (Inner most) - Done
309+
expect(calls[0][1]).toEqual(expect.objectContaining({ streamStatus: 'done' }));
310+
311+
// Level 2 - Loading
312+
expect(calls[1][1]).toEqual(expect.objectContaining({ streamStatus: 'loading' }));
313+
314+
// Level 1 - Loading
315+
expect(calls[2][1]).toEqual(expect.objectContaining({ streamStatus: 'loading' }));
316+
317+
createElementSpy.mockRestore();
318+
});
319+
320+
it('should handle interleaved components correctly', () => {
321+
const components = {
322+
'comp-a': MockComponent,
323+
'comp-b': MockComponent,
324+
};
325+
const renderer = new Renderer({ components });
326+
const createElementSpy = jest.spyOn(React, 'createElement');
327+
328+
// comp-a closed, comp-b closed, comp-a open
329+
const html = '<comp-a>A1</comp-a><comp-b>B1</comp-b><comp-a>A2';
330+
renderer.processHtml(html);
331+
332+
const callsA = createElementSpy.mock.calls.filter(
333+
(call) => call[0] === MockComponent && (call[1] as any).domNode.name === 'comp-a',
334+
);
335+
const callsB = createElementSpy.mock.calls.filter(
336+
(call) => call[0] === MockComponent && (call[1] as any).domNode.name === 'comp-b',
337+
);
338+
339+
expect(callsA.length).toBe(2);
340+
expect(callsB.length).toBe(1);
341+
342+
expect(callsA[0][1]).toEqual(expect.objectContaining({ streamStatus: 'done' }));
343+
expect(callsB[0][1]).toEqual(expect.objectContaining({ streamStatus: 'done' }));
344+
expect(callsA[1][1]).toEqual(expect.objectContaining({ streamStatus: 'loading' }));
345+
346+
createElementSpy.mockRestore();
347+
});
348+
213349
it('should merge class and className attributes correctly', () => {
214350
const components = {
215351
'test-component': MockComponent,

0 commit comments

Comments
 (0)