Skip to content

Commit 74bb16a

Browse files
tests 2
1 parent 018284e commit 74bb16a

File tree

4 files changed

+53
-143
lines changed

4 files changed

+53
-143
lines changed

tests/agent/react/test_json_utils.py

Lines changed: 28 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
from typing import Optional
44

5+
import pytest
56
from pydantic import BaseModel
67

78
from uipath_langchain.agent.react.json_utils import (
@@ -171,57 +172,46 @@ def test_extract_nested_path(self) -> None:
171172
class TestUnwrapOptional:
172173
"""Tests for _unwrap_optional."""
173174

174-
def test_unwraps_optional_type(self) -> None:
175-
result = _unwrap_optional(Optional[str])
176-
assert result is str
177-
178-
def test_non_optional_unchanged(self) -> None:
179-
result = _unwrap_optional(str)
180-
assert result is str
181-
182-
def test_unwraps_optional_basemodel(self) -> None:
183-
result = _unwrap_optional(Optional[Attachment])
184-
assert result is Attachment
175+
@pytest.mark.parametrize(
176+
"input_type,expected",
177+
[
178+
(Optional[str], str),
179+
(str, str),
180+
(Optional[Attachment], Attachment),
181+
],
182+
ids=["optional-str", "plain-str", "optional-basemodel"],
183+
)
184+
def test_unwraps_correctly(self, input_type: type, expected: type) -> None:
185+
assert _unwrap_optional(input_type) is expected
185186

186187

187188
class TestIsPydanticModel:
188189
"""Tests for _is_pydantic_model."""
189190

190-
def test_basemodel_returns_true(self) -> None:
191-
assert _is_pydantic_model(Attachment) is True
192-
193-
def test_str_returns_false(self) -> None:
194-
assert _is_pydantic_model(str) is False
195-
196-
def test_int_returns_false(self) -> None:
197-
assert _is_pydantic_model(int) is False
198-
199-
def test_none_returns_false(self) -> None:
200-
assert _is_pydantic_model(None) is False
201-
202-
def test_instance_returns_false(self) -> None:
203-
assert _is_pydantic_model(Attachment(id="1", filename="f")) is False
191+
@pytest.mark.parametrize(
192+
"value,expected",
193+
[
194+
(Attachment, True),
195+
(str, False),
196+
(None, False),
197+
(Attachment(id="1", filename="f"), False),
198+
],
199+
ids=["basemodel-class", "builtin-type", "none", "instance"],
200+
)
201+
def test_identifies_pydantic_models(self, value: object, expected: bool) -> None:
202+
assert _is_pydantic_model(value) is expected
204203

205204

206205
class TestCreateTypeMatcher:
207206
"""Tests for _create_type_matcher."""
208207

209-
def test_matches_by_name(self) -> None:
208+
def test_matches_by_class_and_string_annotation(self) -> None:
210209
matcher = _create_type_matcher("Attachment", None)
211210
assert matcher(Attachment) is True
211+
assert matcher("Attachment") is True
212+
assert matcher(str) is False
213+
assert matcher("OtherType") is False
212214

213215
def test_matches_by_target_type(self) -> None:
214216
matcher = _create_type_matcher("Attachment", Attachment)
215217
assert matcher(Attachment) is True
216-
217-
def test_no_match_returns_false(self) -> None:
218-
matcher = _create_type_matcher("Attachment", None)
219-
assert matcher(str) is False
220-
221-
def test_string_annotation_match(self) -> None:
222-
matcher = _create_type_matcher("Attachment", None)
223-
assert matcher("Attachment") is True
224-
225-
def test_string_annotation_no_match(self) -> None:
226-
matcher = _create_type_matcher("Attachment", None)
227-
assert matcher("OtherType") is False

tests/agent/react/test_merge_objects.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -200,10 +200,6 @@ def test_empty_left_returns_right(self):
200200
result = reducer_merge_dicts({}, right)
201201
assert result is right
202202

203-
def test_both_empty_returns_left(self):
204-
result = reducer_merge_dicts({}, {})
205-
assert result == {}
206-
207203
def test_disjoint_keys_merged(self):
208204
left = {"a": 1}
209205
right = {"b": 2}

tests/agent/tools/test_mcp_tool.py

Lines changed: 18 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@
1010
AgentResourceType,
1111
)
1212

13-
from uipath_langchain.agent.tools.mcp_tool import (
13+
from uipath_langchain.agent.tools.mcp.mcp_tool import (
1414
_deduplicate_tools,
1515
_filter_tools,
1616
create_mcp_tools,
17-
create_mcp_tools_from_metadata,
17+
create_mcp_tools_from_metadata_for_mcp_server,
1818
)
1919

2020

@@ -52,35 +52,19 @@ def _make_mcp_resource(
5252
class TestDeduplicateTools:
5353
"""Tests for _deduplicate_tools."""
5454

55-
def test_no_duplicates_unchanged(self) -> None:
55+
def test_unique_names_unchanged(self) -> None:
5656
tools = [_make_tool("alpha"), _make_tool("beta"), _make_tool("gamma")]
5757
result = _deduplicate_tools(tools)
5858
assert [t.name for t in result] == ["alpha", "beta", "gamma"]
5959

60-
def test_all_duplicates_get_suffix(self) -> None:
61-
tools = [_make_tool("search"), _make_tool("search"), _make_tool("search")]
60+
def test_duplicate_names_get_numeric_suffix(self) -> None:
61+
tools = [_make_tool("search"), _make_tool("calc"), _make_tool("search")]
6262
result = _deduplicate_tools(tools)
63-
assert [t.name for t in result] == ["search_1", "search_2", "search_3"]
64-
65-
def test_partial_duplicates(self) -> None:
66-
tools = [
67-
_make_tool("search"),
68-
_make_tool("calc"),
69-
_make_tool("search"),
70-
]
71-
result = _deduplicate_tools(tools)
72-
assert result[0].name == "search_1"
73-
assert result[1].name == "calc"
74-
assert result[2].name == "search_2"
63+
assert [t.name for t in result] == ["search_1", "calc", "search_2"]
7564

7665
def test_empty_list(self) -> None:
7766
assert _deduplicate_tools([]) == []
7867

79-
def test_single_tool(self) -> None:
80-
tools = [_make_tool("only")]
81-
result = _deduplicate_tools(tools)
82-
assert result[0].name == "only"
83-
8468

8569
class TestFilterTools:
8670
"""Tests for _filter_tools."""
@@ -158,17 +142,11 @@ async def test_disabled_configs_yield_empty(
158142
monkeypatch.setenv("UIPATH_URL", "https://example.com")
159143
monkeypatch.setenv("UIPATH_ACCESS_TOKEN", "test-token")
160144

145+
# Both single config and list of configs should yield empty
161146
cfg = _make_mcp_resource(is_enabled=False)
162147
async with create_mcp_tools(cfg) as tools:
163148
assert tools == []
164149

165-
@pytest.mark.asyncio
166-
async def test_all_disabled_in_list_yield_empty(
167-
self, monkeypatch: pytest.MonkeyPatch
168-
) -> None:
169-
monkeypatch.setenv("UIPATH_URL", "https://example.com")
170-
monkeypatch.setenv("UIPATH_ACCESS_TOKEN", "test-token")
171-
172150
configs = [
173151
_make_mcp_resource(is_enabled=False),
174152
_make_mcp_resource(is_enabled=False),
@@ -178,10 +156,10 @@ async def test_all_disabled_in_list_yield_empty(
178156

179157

180158
class TestCreateMcpToolsFromMetadata:
181-
"""Tests for create_mcp_tools_from_metadata."""
159+
"""Tests for create_mcp_tools_from_metadata_for_mcp_server."""
182160

183161
@pytest.mark.asyncio
184-
async def test_creates_tools_from_available_tools(self) -> None:
162+
async def test_creates_tools_with_correct_metadata(self) -> None:
185163
mcp_tools = [
186164
AgentMcpTool(
187165
name="get_weather",
@@ -201,38 +179,27 @@ async def test_creates_tools_from_available_tools(self) -> None:
201179
),
202180
]
203181
cfg = _make_mcp_resource(available_tools=mcp_tools)
182+
mock_client = MagicMock()
204183

205-
tools = await create_mcp_tools_from_metadata(cfg)
184+
tools = await create_mcp_tools_from_metadata_for_mcp_server(cfg, mock_client)
206185

207186
assert len(tools) == 2
208187
assert tools[0].name == "get_weather"
209-
assert tools[1].name == "search_docs"
210188
assert tools[0].description == "Get weather data"
211-
212-
@pytest.mark.asyncio
213-
async def test_tool_metadata_contains_expected_fields(self) -> None:
214-
mcp_tools = [
215-
AgentMcpTool(
216-
name="my_tool",
217-
description="A tool",
218-
inputSchema={"type": "object", "properties": {}},
219-
),
220-
]
221-
cfg = _make_mcp_resource(available_tools=mcp_tools)
222-
223-
tools = await create_mcp_tools_from_metadata(cfg)
224-
189+
assert tools[1].name == "search_docs"
190+
# Validate metadata on first tool
225191
assert tools[0].metadata is not None
226192
assert tools[0].metadata["tool_type"] == "mcp"
227-
assert tools[0].metadata["display_name"] == "my_tool"
193+
assert tools[0].metadata["display_name"] == "get_weather"
228194
assert tools[0].metadata["folder_path"] == "/Shared"
229195
assert tools[0].metadata["slug"] == "test-slug"
230196

231197
@pytest.mark.asyncio
232198
async def test_empty_available_tools_returns_empty(self) -> None:
233199
cfg = _make_mcp_resource(available_tools=[])
200+
mock_client = MagicMock()
234201

235-
tools = await create_mcp_tools_from_metadata(cfg)
202+
tools = await create_mcp_tools_from_metadata_for_mcp_server(cfg, mock_client)
236203

237204
assert tools == []
238205

@@ -246,9 +213,9 @@ async def test_tool_name_sanitized(self) -> None:
246213
),
247214
]
248215
cfg = _make_mcp_resource(available_tools=mcp_tools)
216+
mock_client = MagicMock()
249217

250-
tools = await create_mcp_tools_from_metadata(cfg)
218+
tools = await create_mcp_tools_from_metadata_for_mcp_server(cfg, mock_client)
251219

252-
# sanitize_tool_name replaces spaces with underscores and strips non-alphanum
253220
assert " " not in tools[0].name
254221
assert "!" not in tools[0].name

tests/agent/tools/test_process_tool.py

Lines changed: 7 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -54,60 +54,22 @@ def process_resource_with_input() -> AgentProcessToolResourceConfig:
5454
)
5555

5656

57-
class TestProcessToolMetadata:
58-
"""Test that process tool has correct metadata for observability."""
57+
class TestProcessToolCreation:
58+
"""Test process tool creation, metadata, and structural properties."""
5959

60-
def test_process_tool_has_metadata(
60+
def test_tool_properties_and_metadata(
6161
self, process_resource: AgentProcessToolResourceConfig
6262
) -> None:
6363
tool = create_process_tool(process_resource)
6464

65-
assert tool.metadata is not None
66-
assert isinstance(tool.metadata, dict)
67-
68-
def test_process_tool_metadata_has_tool_type(
69-
self, process_resource: AgentProcessToolResourceConfig
70-
) -> None:
71-
tool = create_process_tool(process_resource)
65+
assert tool.name == "test_process"
66+
assert tool.description == "Test process description"
67+
assert tool.coroutine is not None
7268
assert tool.metadata is not None
7369
assert tool.metadata["tool_type"] == "process"
74-
75-
def test_process_tool_metadata_has_display_name(
76-
self, process_resource: AgentProcessToolResourceConfig
77-
) -> None:
78-
tool = create_process_tool(process_resource)
79-
assert tool.metadata is not None
8070
assert tool.metadata["display_name"] == "MyProcess"
81-
82-
def test_process_tool_metadata_has_folder_path(
83-
self, process_resource: AgentProcessToolResourceConfig
84-
) -> None:
85-
tool = create_process_tool(process_resource)
86-
assert tool.metadata is not None
8771
assert tool.metadata["folder_path"] == "/Shared/MyFolder"
8872

89-
90-
class TestProcessToolCreation:
91-
"""Test process tool structural properties."""
92-
93-
def test_tool_name_matches_resource_name(
94-
self, process_resource: AgentProcessToolResourceConfig
95-
) -> None:
96-
tool = create_process_tool(process_resource)
97-
assert tool.name == "test_process"
98-
99-
def test_tool_description_matches_resource(
100-
self, process_resource: AgentProcessToolResourceConfig
101-
) -> None:
102-
tool = create_process_tool(process_resource)
103-
assert tool.description == "Test process description"
104-
105-
def test_tool_is_async(
106-
self, process_resource: AgentProcessToolResourceConfig
107-
) -> None:
108-
tool = create_process_tool(process_resource)
109-
assert tool.coroutine is not None
110-
11173
def test_tool_name_sanitized_for_special_chars(self) -> None:
11274
resource = AgentProcessToolResourceConfig(
11375
type=AgentToolType.PROCESS,
@@ -125,16 +87,11 @@ def test_tool_name_sanitized_for_special_chars(self) -> None:
12587
assert "(" not in tool.name
12688
assert "!" not in tool.name
12789

128-
def test_tool_with_input_schema_has_args_schema(
90+
def test_tool_with_input_schema(
12991
self, process_resource_with_input: AgentProcessToolResourceConfig
13092
) -> None:
13193
tool = create_process_tool(process_resource_with_input)
13294
assert tool.args_schema is not None
133-
134-
def test_tool_metadata_includes_args_schema(
135-
self, process_resource_with_input: AgentProcessToolResourceConfig
136-
) -> None:
137-
tool = create_process_tool(process_resource_with_input)
13895
assert tool.metadata is not None
13996
assert "args_schema" in tool.metadata
14097

0 commit comments

Comments
 (0)