@@ -184,6 +184,192 @@ def build(
184184 ):
185185 _app = DummyJSONRPCApp (** mock_app_params )
186186
187+ @pytest .mark .asyncio
188+ async def test_stream_send_timeout_applied_to_event_source_response (
189+ self , mock_app_params : dict
190+ ):
191+ """Test that stream_send_timeout is correctly applied to EventSourceResponse."""
192+ from unittest .mock import patch
193+
194+ class DummyJSONRPCApp (JSONRPCApplication ):
195+ def __init__ (self , ** kwargs ):
196+ # Skip parent __init__ to avoid package checks
197+ self .stream_send_timeout = kwargs .get (
198+ 'stream_send_timeout' , None
199+ )
200+ self .agent_card = kwargs .get ('agent_card' )
201+ self .extended_agent_card = kwargs .get ('extended_agent_card' )
202+ self .card_modifier = kwargs .get ('card_modifier' )
203+ self .extended_card_modifier = kwargs .get (
204+ 'extended_card_modifier'
205+ )
206+ self .max_content_length = kwargs .get (
207+ 'max_content_length' , 10 * 1024 * 1024
208+ )
209+ self .handler = kwargs .get ('http_handler' )
210+
211+ def build (self , ** kwargs ):
212+ return object ()
213+
214+ # Test with app-level timeout
215+ app = DummyJSONRPCApp (stream_send_timeout = 30.0 , ** mock_app_params )
216+
217+ # Mock context
218+ context = MagicMock (spec = ServerCallContext )
219+ context .state = {}
220+ context .activated_extensions = None
221+
222+ # Mock streaming handler result
223+ async def mock_generator ():
224+ yield SendMessageResponse (
225+ root = SendMessageSuccessResponse (
226+ message = Message (
227+ message_id = '1' ,
228+ role = Role .assistant ,
229+ parts = [Part (TextPart (text = 'test' ))],
230+ )
231+ )
232+ )
233+
234+ handler_result = mock_generator ()
235+
236+ with patch (
237+ 'a2a.server.apps.jsonrpc.jsonrpc_app.EventSourceResponse'
238+ ) as mock_esr :
239+ mock_esr .return_value = MagicMock ()
240+
241+ # Call the method
242+ response = app ._create_response (context , handler_result )
243+
244+ # Assert EventSourceResponse was called with correct timeout
245+ mock_esr .assert_called_once ()
246+ call_args = mock_esr .call_args
247+ assert call_args [1 ]['send_timeout' ] == 30.0
248+
249+ @pytest .mark .asyncio
250+ async def test_stream_send_timeout_none_disables_timeout (
251+ self , mock_app_params : dict
252+ ):
253+ """Test that stream_send_timeout=None disables the timeout."""
254+ from unittest .mock import patch
255+
256+ class DummyJSONRPCApp (JSONRPCApplication ):
257+ def __init__ (self , ** kwargs ):
258+ # Skip parent __init__ to avoid package checks
259+ self .stream_send_timeout = kwargs .get (
260+ 'stream_send_timeout' , None
261+ )
262+ self .agent_card = kwargs .get ('agent_card' )
263+ self .extended_agent_card = kwargs .get ('extended_agent_card' )
264+ self .card_modifier = kwargs .get ('card_modifier' )
265+ self .extended_card_modifier = kwargs .get (
266+ 'extended_card_modifier'
267+ )
268+ self .max_content_length = kwargs .get (
269+ 'max_content_length' , 10 * 1024 * 1024
270+ )
271+ self .handler = kwargs .get ('http_handler' )
272+
273+ def build (self , ** kwargs ):
274+ return object ()
275+
276+ # Test with None timeout (default)
277+ app = DummyJSONRPCApp (stream_send_timeout = None , ** mock_app_params )
278+
279+ # Mock context
280+ context = MagicMock (spec = ServerCallContext )
281+ context .state = {}
282+ context .activated_extensions = None
283+
284+ # Mock streaming handler result
285+ async def mock_generator ():
286+ yield SendMessageResponse (
287+ root = SendMessageSuccessResponse (
288+ message = Message (
289+ message_id = '1' ,
290+ role = Role .assistant ,
291+ parts = [Part (TextPart (text = 'test' ))],
292+ )
293+ )
294+ )
295+
296+ handler_result = mock_generator ()
297+
298+ with patch (
299+ 'a2a.server.apps.jsonrpc.jsonrpc_app.EventSourceResponse'
300+ ) as mock_esr :
301+ mock_esr .return_value = MagicMock ()
302+
303+ # Call the method
304+ response = app ._create_response (context , handler_result )
305+
306+ # Assert EventSourceResponse was called with None (disabled timeout)
307+ mock_esr .assert_called_once ()
308+ call_args = mock_esr .call_args
309+ assert call_args [1 ]['send_timeout' ] is None
310+
311+ @pytest .mark .asyncio
312+ async def test_stream_send_timeout_context_override (
313+ self , mock_app_params : dict
314+ ):
315+ """Test that context.state can override the app-level stream_send_timeout."""
316+ from unittest .mock import patch
317+
318+ class DummyJSONRPCApp (JSONRPCApplication ):
319+ def __init__ (self , ** kwargs ):
320+ # Skip parent __init__ to avoid package checks
321+ self .stream_send_timeout = kwargs .get (
322+ 'stream_send_timeout' , None
323+ )
324+ self .agent_card = kwargs .get ('agent_card' )
325+ self .extended_agent_card = kwargs .get ('extended_agent_card' )
326+ self .card_modifier = kwargs .get ('card_modifier' )
327+ self .extended_card_modifier = kwargs .get (
328+ 'extended_card_modifier'
329+ )
330+ self .max_content_length = kwargs .get (
331+ 'max_content_length' , 10 * 1024 * 1024
332+ )
333+ self .handler = kwargs .get ('http_handler' )
334+
335+ def build (self , ** kwargs ):
336+ return object ()
337+
338+ # Test with app-level timeout
339+ app = DummyJSONRPCApp (stream_send_timeout = 30.0 , ** mock_app_params )
340+
341+ # Mock context with override
342+ context = MagicMock (spec = ServerCallContext )
343+ context .state = {'stream_send_timeout' : 60.0 }
344+ context .activated_extensions = None
345+
346+ # Mock streaming handler result
347+ async def mock_generator ():
348+ yield SendMessageResponse (
349+ root = SendMessageSuccessResponse (
350+ message = Message (
351+ message_id = '1' ,
352+ role = Role .assistant ,
353+ parts = [Part (TextPart (text = 'test' ))],
354+ )
355+ )
356+ )
357+
358+ handler_result = mock_generator ()
359+
360+ with patch (
361+ 'a2a.server.apps.jsonrpc.jsonrpc_app.EventSourceResponse'
362+ ) as mock_esr :
363+ mock_esr .return_value = MagicMock ()
364+
365+ # Call the method
366+ response = app ._create_response (context , handler_result )
367+
368+ # Assert EventSourceResponse was called with context override
369+ mock_esr .assert_called_once ()
370+ call_args = mock_esr .call_args
371+ assert call_args [1 ]['send_timeout' ] == 60.0
372+
187373
188374class TestJSONRPCExtensions :
189375 @pytest .fixture
0 commit comments