1
1
#!/usr/bin/env python
2
2
"""Comprehensive tests for EventTranslator, focusing on untested paths."""
3
3
4
+ import json
5
+ from dataclasses import asdict , dataclass
6
+ from types import SimpleNamespace
7
+
4
8
import pytest
5
9
import uuid
6
10
from unittest .mock import MagicMock , patch , AsyncMock
7
11
8
12
from ag_ui .core import (
9
13
EventType , TextMessageStartEvent , TextMessageContentEvent , TextMessageEndEvent ,
10
- ToolCallStartEvent , ToolCallArgsEvent , ToolCallEndEvent , StateDeltaEvent , CustomEvent
14
+ ToolCallStartEvent , ToolCallArgsEvent , ToolCallEndEvent , ToolCallResultEvent ,
15
+ StateDeltaEvent , CustomEvent
11
16
)
12
17
from google .adk .events import Event as ADKEvent
13
18
from ag_ui_adk .event_translator import EventTranslator
@@ -109,15 +114,68 @@ async def test_translate_function_calls_detection(self, translator, mock_adk_eve
109
114
async def test_translate_function_responses_handling (self , translator , mock_adk_event ):
110
115
"""Test function responses handling."""
111
116
# Mock event with function responses
112
- mock_function_response = MagicMock ()
113
- mock_adk_event .get_function_responses = MagicMock (return_value = [mock_function_response ])
117
+ function_response = SimpleNamespace (id = "tool-1" , response = {"ok" : True })
118
+ mock_adk_event .get_function_calls = MagicMock (return_value = [])
119
+ mock_adk_event .get_function_responses = MagicMock (return_value = [function_response ])
114
120
115
121
events = []
116
122
async for event in translator .translate (mock_adk_event , "thread_1" , "run_1" ):
117
123
events .append (event )
118
124
119
- # Function responses should be handled but not emit events
120
- assert len (events ) == 0
125
+ assert len (events ) == 1
126
+ event = events [0 ]
127
+ assert isinstance (event , ToolCallResultEvent )
128
+ assert json .loads (event .content ) == {"ok" : True }
129
+
130
+ @pytest .mark .asyncio
131
+ async def test_translate_function_response_with_call_tool_result_payload (self , translator ):
132
+ """Ensure complex CallToolResult payloads are serialized correctly."""
133
+
134
+ @dataclass
135
+ class TextContent :
136
+ type : str = "text"
137
+ text : str = ""
138
+ annotations : list | None = None
139
+ meta : dict | None = None
140
+
141
+ @dataclass
142
+ class CallToolResult :
143
+ meta : dict | None
144
+ structuredContent : dict | None
145
+ isError : bool
146
+ content : list [TextContent ]
147
+
148
+ repeated_text_entries = [
149
+ "Primary Task: Provide a detailed walkthrough for the requested topic." ,
150
+ "Primary Task: Provide a detailed walkthrough for the requested topic." ,
151
+ "Constraints: Ensure clarity and maintain a concise explanation." ,
152
+ "Constraints: Ensure clarity and maintain a concise explanation." ,
153
+ ]
154
+
155
+ payload = CallToolResult (
156
+ meta = None ,
157
+ structuredContent = None ,
158
+ isError = False ,
159
+ content = [TextContent (text = text ) for text in repeated_text_entries ],
160
+ )
161
+
162
+ function_response = SimpleNamespace (
163
+ id = "tool-structured-1" ,
164
+ response = {"result" : payload },
165
+ )
166
+
167
+ events = []
168
+ async for event in translator ._translate_function_response ([function_response ]):
169
+ events .append (event )
170
+
171
+ assert len (events ) == 1
172
+ event = events [0 ]
173
+ assert isinstance (event , ToolCallResultEvent )
174
+
175
+ content = json .loads (event .content )
176
+ assert content ["result" ]["isError" ] is False
177
+ assert content ["result" ]["structuredContent" ] is None
178
+ assert [item ["text" ] for item in content ["result" ]["content" ]] == repeated_text_entries
121
179
122
180
@pytest .mark .asyncio
123
181
async def test_translate_state_delta_event (self , translator , mock_adk_event ):
@@ -781,4 +839,4 @@ async def test_partial_streaming_continuation(self, translator, mock_adk_event_w
781
839
782
840
# Should reset streaming state
783
841
assert translator ._is_streaming is False
784
- assert translator ._streaming_message_id is None
842
+ assert translator ._streaming_message_id is None
0 commit comments