13
13
# limitations under the License.
14
14
15
15
from inspect import Parameter , signature
16
- from typing import Optional
16
+ from typing import Any , Optional
17
17
18
18
import pytest
19
19
import pytest_asyncio
@@ -68,7 +68,7 @@ async def test_load_toolset_specific(
68
68
async def test_load_toolset_default (self , toolbox : ToolboxClient ):
69
69
"""Load the default toolset, i.e. all tools."""
70
70
toolset = await toolbox .load_toolset ()
71
- assert len (toolset ) == 6
71
+ assert len (toolset ) == 7
72
72
tool_names = {tool .__name__ for tool in toolset }
73
73
expected_tools = [
74
74
"get-row-by-content-auth" ,
@@ -77,6 +77,7 @@ async def test_load_toolset_default(self, toolbox: ToolboxClient):
77
77
"get-row-by-id" ,
78
78
"get-n-rows" ,
79
79
"search-rows" ,
80
+ "process-data" ,
80
81
]
81
82
assert tool_names == set (expected_tools )
82
83
@@ -379,3 +380,66 @@ async def test_run_tool_with_different_id(self, toolbox: ToolboxClient):
379
380
response = await tool (
email = "[email protected] " ,
id = 4 ,
data = "row3" )
380
381
assert isinstance (response , str )
381
382
assert response == "null"
383
+
384
+
385
+ @pytest .mark .asyncio
386
+ @pytest .mark .usefixtures ("toolbox_server" )
387
+ class TestMapParams :
388
+ """
389
+ End-to-end tests for tools with map parameters.
390
+ """
391
+
392
+ async def test_tool_signature_with_map_params (self , toolbox : ToolboxClient ):
393
+ """Verify the client correctly constructs the signature for a tool with map params."""
394
+ tool = await toolbox .load_tool ("process-data" )
395
+ sig = signature (tool )
396
+
397
+ assert "execution_context" in sig .parameters
398
+ assert sig .parameters ["execution_context" ].annotation == dict [str , Any ]
399
+ assert sig .parameters ["execution_context" ].default is Parameter .empty
400
+
401
+ assert "user_scores" in sig .parameters
402
+ assert sig .parameters ["user_scores" ].annotation == dict [str , int ]
403
+ assert sig .parameters ["user_scores" ].default is Parameter .empty
404
+
405
+ assert "feature_flags" in sig .parameters
406
+ assert sig .parameters ["feature_flags" ].annotation == Optional [dict [str , bool ]]
407
+ assert sig .parameters ["feature_flags" ].default is None
408
+
409
+ async def test_run_tool_with_map_params (self , toolbox : ToolboxClient ):
410
+ """Invoke a tool with valid map parameters."""
411
+ tool = await toolbox .load_tool ("process-data" )
412
+
413
+ response = await tool (
414
+ execution_context = {"env" : "prod" , "id" : 1234 , "user" : 1234.5 },
415
+ user_scores = {"user1" : 100 , "user2" : 200 },
416
+ feature_flags = {"new_feature" : True },
417
+ )
418
+ assert isinstance (response , str )
419
+ assert '"execution_context":{"env":"prod","id",1234,"user":1234.5}' in response
420
+ assert '"user_scores":{"user1":100,"user2":200}' in response
421
+ assert '"feature_flags":{"new_feature":true}' in response
422
+
423
+ async def test_run_tool_with_optional_map_param_omitted (
424
+ self , toolbox : ToolboxClient
425
+ ):
426
+ """Invoke a tool without the optional map parameter."""
427
+ tool = await toolbox .load_tool ("process-data" )
428
+
429
+ response = await tool (
430
+ execution_context = {"env" : "dev" }, user_scores = {"user3" : 300 }
431
+ )
432
+ assert isinstance (response , str )
433
+ assert '"execution_context":{"env":"dev"}' in response
434
+ assert '"user_scores":{"user3":300}' in response
435
+ assert "feature_flags" not in response
436
+
437
+ async def test_run_tool_with_wrong_map_value_type (self , toolbox : ToolboxClient ):
438
+ """Invoke a tool with a map parameter having the wrong value type."""
439
+ tool = await toolbox .load_tool ("process-data" )
440
+
441
+ with pytest .raises (ValidationError ):
442
+ await tool (
443
+ execution_context = {"env" : "staging" },
444
+ user_scores = {"user4" : "not-an-integer" },
445
+ )
0 commit comments