Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 21 additions & 7 deletions packages/middleware/node/test/streamableHttp.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,23 @@ async function readSSEEvent(response: Response): Promise<string> {
return new TextDecoder().decode(value);
}

/**
* Read from an SSE response until the accumulated text satisfies the predicate,
* or the stream ends. Fetch may deliver SSE events in separate chunks, so tests
* must not assume a single read contains every event.
*/
async function readSSEEventUntil(reader: ReadableStreamDefaultReader<Uint8Array>, predicate: (text: string) => boolean): Promise<string> {
const decoder = new TextDecoder();
let text = '';
for (;;) {
const { value, done } = await reader.read();
if (value) text += decoder.decode(value, { stream: true });
if (predicate(text)) break;
if (done) break;
}
return text;
}

/**
* Helper to send JSON-RPC request
*/
Expand Down Expand Up @@ -727,9 +744,8 @@ describe('Zod v4', () => {

const reader = response.body?.getReader();

// The responses may come in any order or together in one chunk
const { value } = await reader!.read();
const text = new TextDecoder().decode(value);
// The responses may arrive in any order or in separate chunks
const text = await readSSEEventUntil(reader!, t => t.includes('"id":"req-1"') && t.includes('"id":"req-2"'));

// Check that both responses were sent on the same stream
expect(text).toContain('"id":"req-1"');
Expand Down Expand Up @@ -1482,8 +1498,7 @@ describe('Zod v4', () => {

// Read the notification from the SSE stream
const reader = sseResponse.body?.getReader();
const { value } = await reader!.read();
const text = new TextDecoder().decode(value);
const text = await readSSEEventUntil(reader!, t => t.includes('First notification from MCP server') && t.includes('id: '));

// Verify the notification was sent with an event ID
expect(text).toContain('id: ');
Expand Down Expand Up @@ -1515,8 +1530,7 @@ describe('Zod v4', () => {

// Read the replayed notification
const reconnectReader = reconnectResponse.body?.getReader();
const reconnectData = await reconnectReader!.read();
const reconnectText = new TextDecoder().decode(reconnectData.value);
const reconnectText = await readSSEEventUntil(reconnectReader!, t => t.includes('Second notification from MCP server'));

// Verify we received the second notification that was sent after our stored eventId
expect(reconnectText).toContain('Second notification from MCP server');
Expand Down
Loading